GCC Code Coverage Report


Directory: ./
File: storage/innobase/handler/ha_innodb.cc
Date: 2022-12-13 11:44:05
Exec Total Coverage
Lines: 8733 10087 86.6%
Branches: 8470 15110 56.1%

Line Branch Exec Source
1 /*****************************************************************************
2
3 Copyright (c) 2000, 2022, Oracle and/or its affiliates.
4 Copyright (c) 2008, 2009 Google Inc.
5 Copyright (c) 2009, Percona Inc.
6 Copyright (c) 2012, Facebook Inc.
7
8 Portions of this file contain modifications contributed and copyrighted by
9 Google, Inc. Those modifications are gratefully acknowledged and are described
10 briefly in the InnoDB documentation. The contributions by Google are
11 incorporated with their permission, and subject to the conditions contained in
12 the file COPYING.Google.
13
14 Portions of this file contain modifications contributed and copyrighted
15 by Percona Inc.. Those modifications are
16 gratefully acknowledged and are described briefly in the InnoDB
17 documentation. The contributions by Percona Inc. are incorporated with
18 their permission, and subject to the conditions contained in the file
19 COPYING.Percona.
20
21 This program is free software; you can redistribute it and/or modify it under
22 the terms of the GNU General Public License, version 2.0, as published by the
23 Free Software Foundation.
24
25 This program is also distributed with certain software (including but not
26 limited to OpenSSL) that is licensed under separate terms, as designated in a
27 particular file or component or in included license documentation. The authors
28 of MySQL hereby grant you an additional permission to link the program and
29 your derivative works with the separately licensed software that they have
30 included with MySQL.
31
32 This program is distributed in the hope that it will be useful, but WITHOUT
33 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
34 FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
35 for more details.
36
37 You should have received a copy of the GNU General Public License along with
38 this program; if not, write to the Free Software Foundation, Inc.,
39 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
40
41 *****************************************************************************/
42
43 /** @file ha_innodb.cc */
44
45 #ifndef UNIV_HOTBACKUP
46 #include "my_config.h"
47 #endif /* !UNIV_HOTBACKUP */
48
49 #include <auto_thd.h>
50 #include <errno.h>
51 #include <fcntl.h>
52 #include <gstream.h>
53 #include <limits.h>
54 #include <log.h>
55 #include <math.h>
56 #include <my_compare.h>
57 #include <mysqld.h>
58 #include <stdlib.h>
59 #include <strfunc.h>
60 #include <time.h>
61
62 #include <algorithm>
63
64 #include <sql_table.h>
65 #include "mysql/components/services/system_variable_source.h"
66
67 #ifndef UNIV_HOTBACKUP
68 #include <current_thd.h>
69 #include <debug_sync.h>
70 #include <derror.h>
71 #include <my_bitmap.h>
72 #include <my_check_opt.h>
73 #include <mysql/service_thd_alloc.h>
74 #include <mysql/service_thd_wait.h>
75 #include <mysql_com.h>
76 #include <sql_acl.h>
77 #include <sql_class.h>
78 #include <sql_show.h>
79 #include <sql_tablespace.h>
80 #include <sql_thd_internal_api.h>
81 #include <sys_vars_shared.h>
82 #include "api0api.h"
83 #include "api0misc.h"
84 #include "arch0arch.h"
85 #include "arch0page.h"
86 #include "auth_acls.h"
87 #include "btr0btr.h"
88 #include "btr0cur.h"
89 #include "btr0sea.h"
90 #include "buf0dblwr.h"
91 #include "buf0dump.h"
92 #include "buf0flu.h"
93 #include "buf0lru.h"
94 #include "buf0stats.h"
95 #include "clone0api.h"
96 #include "clone0clone.h"
97 #include "dd/dd.h"
98 #include "dd/dictionary.h"
99 #include "dd/impl/bootstrap/bootstrap_ctx.h"
100 #include "dd/properties.h"
101 #include "dd/types/index.h"
102 #include "dd/types/object_table.h"
103 #include "dd/types/object_table_definition.h"
104 #include "dd/types/partition.h"
105 #include "dd/types/table.h"
106 #include "dd/types/tablespace.h"
107 #include "ddl0ddl.h"
108 #include "dict0boot.h"
109 #include "dict0crea.h"
110 #include "dict0dd.h"
111 #include "dict0dict.h"
112 #include "dict0load.h"
113 #include "dict0stats.h"
114 #include "dict0stats_bg.h"
115 #include "fil0crypt.h"
116 #include "fil0fil.h"
117 #include "fsp0fsp.h"
118 #include "fsp0space.h"
119 #include "fsp0sysspace.h"
120 #include "fts0fts.h"
121 #include "fts0plugin.h"
122 #include "fts0priv.h"
123 #include "fts0tokenize.h" // true_word_char
124 #include "fts0types.h"
125 #include "ha_innodb.h"
126 #include "ha_innopart.h"
127 #include "ha_prototypes.h"
128 #include "i_s.h"
129 #include "ibuf0ibuf.h"
130 #include "lex_string.h"
131 #include "lob0lob.h"
132 #include "lock0lock.h"
133 #include "log0buf.h"
134 #include "log0chkp.h"
135 #include "log0encryption.h"
136 #include "log0meb.h"
137 #include "log0pfs.h"
138 #include "log0pre_8_0_30.h"
139 #include "log0write.h"
140 #include "mem0mem.h"
141 #include "mtr0mtr.h"
142 #include "my_compare.h"
143 #include "my_compiler.h"
144 #include "my_dbug.h"
145 #include "my_double2ulonglong.h"
146 #include "my_io.h"
147 #include "my_macros.h"
148 #include "my_psi_config.h"
149 #include "mysql/components/services/log_builtins.h"
150 #include "mysql/plugin.h"
151 #include "mysql/psi/mysql_data_lock.h"
152 #include "mysys_err.h"
153 #include "os0thread-create.h"
154 #include "os0thread.h"
155 #include "p_s.h"
156 #include "page0zip.h"
157 #include "pars0pars.h"
158 #include "rem0types.h"
159 #include "row0ext.h"
160 #include "row0import.h"
161 #include "row0ins.h"
162 #include "row0mysql.h"
163 #include "row0quiesce.h"
164 #include "row0sel.h"
165 #include "row0upd.h"
166 #include "sql/plugin_table.h"
167 #include "srv0mon.h"
168 #include "srv0srv.h"
169 #include "srv0start.h"
170 #include "sync0sync.h"
171 #ifdef UNIV_DEBUG
172 #include "trx0purge.h"
173 #endif /* UNIV_DEBUG */
174 #include "dict0priv.h"
175 #include "dict0sdi.h"
176 #include "dict0upgrade.h"
177 #include "os0thread-create.h"
178 #include "os0thread.h"
179 #include "sql/auth/auth_common.h"
180 #include "sql/item.h"
181 #include "sql_base.h"
182 #include "srv0tmp.h"
183 #include "trx0rec.h"
184 #include "trx0roll.h"
185 #include "trx0rseg.h"
186 #include "trx0sys.h"
187 #include "trx0trx.h"
188 #include "trx0xa.h"
189 #include "ut0mem.h"
190 #include "ut0test.h"
191 #include "xtradb_i_s.h"
192 #else
193 #include <typelib.h>
194 #include "buf0types.h"
195 #include "univ.i"
196 #endif /* !UNIV_HOTBACKUP */
197
198 #include "log0files_io.h"
199
200 #include "sql-common/json_binary.h"
201 #include "sql-common/json_dom.h"
202
203 #ifdef WITH_WSREP
204 #include "my_md5.h"
205 #include "tc_log.h"
206 #include "wsrep_api.h"
207 #include "wsrep_mysqld.h"
208
209 /* Must always init to false. */
210 static bool innobase_disallow_writes = false;
211
212 extern bool wsrep_prepare_key_for_innodb(const uchar *cache_key,
213 size_t cache_key_len,
214 const uchar *row_id, size_t row_id_len,
215 wsrep_buf_t *key, size_t *key_len);
216 #endif /* WITH_WSREP */
217
218 #include "os0enc.h"
219 #include "os0file.h"
220
221 #include <mutex>
222 #include <sstream>
223 #include <string>
224 #include <vector>
225
226 #ifdef HAVE_UNISTD_H
227 #include <unistd.h>
228 #endif /* HAVE_UNISTD_H */
229
230 #ifndef UNIV_HOTBACKUP
231
232 namespace innobase {
233 namespace component_services {
234 SERVICE_TYPE(registry) *reg_srv = nullptr;
235
236 /** Initialize component service handles */
237 9726 static bool intitialize_service_handles() {
238
1/2
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
9726 DBUG_TRACE;
239
240 auto cleanup = [&]() {
241 /* Add module specific deinitialization here */
242 innobase::encryption::deinit_keyring_services(reg_srv);
243 mysql_plugin_registry_release(reg_srv);
244 };
245
246
1/2
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
9726 reg_srv = mysql_plugin_registry_acquire();
247
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 if (reg_srv == nullptr) {
248 return false;
249 }
250
251 /* Add module specific initialization here */
252
2/4
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9726 times.
9726 if (innobase::encryption::init_keyring_services(reg_srv) == false) {
253 cleanup();
254 return false;
255 }
256
257 /* During initialize, PFS is not ready. */
258
3/4
✓ Branch 0 taken 9516 times.
✓ Branch 1 taken 210 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9726 times.
19242 if (!opt_initialize &&
259
2/4
✓ Branch 0 taken 9516 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9516 times.
9516 !log_pfs_acquire_services(innobase::component_services::reg_srv)) {
260 ib::warn(ER_IB_MSG_LOG_PFS_ACQUIRE_SERVICES_FAILED);
261 }
262
263 9726 return true;
264 9726 }
265
266 /** Deinitialize compoent service handles */
267 8462 static void deinitialize_service_handles() {
268
1/2
✓ Branch 0 taken 8462 times.
✗ Branch 1 not taken.
8462 DBUG_TRACE;
269
2/2
✓ Branch 0 taken 8248 times.
✓ Branch 1 taken 214 times.
8462 if (!opt_initialize) {
270
1/2
✓ Branch 0 taken 8248 times.
✗ Branch 1 not taken.
8248 log_pfs_release_services(reg_srv);
271 }
272
1/2
✓ Branch 0 taken 8462 times.
✗ Branch 1 not taken.
8462 innobase::encryption::deinit_keyring_services(reg_srv);
273
2/2
✓ Branch 0 taken 8454 times.
✓ Branch 1 taken 8 times.
8462 if (reg_srv != nullptr) {
274
1/2
✓ Branch 0 taken 8454 times.
✗ Branch 1 not taken.
8454 mysql_plugin_registry_release(reg_srv);
275 }
276 8462 }
277
278 } // namespace component_services
279 } // namespace innobase
280
281 /** Stop printing warnings, if the count exceeds this threshold. */
282 static const size_t MOVED_FILES_PRINT_THRESHOLD = 32;
283
284 SERVICE_TYPE(registry) * reg_svc;
285 SERVICE_TYPE(system_variable_source) * sysvar_source_svc;
286 SERVICE_TYPE(clone_protocol) * clone_protocol_svc;
287
288 static const uint64_t KB = 1024;
289 static const uint64_t MB = KB * 1024;
290 static const uint64_t GB = MB * 1024;
291
292 /** fil_space_t::flags for hard-coded tablespaces */
293 uint32_t predefined_flags;
294
295 /** to protect innobase_open_files */
296 static mysql_mutex_t innobase_share_mutex;
297
298 /* mutex protecting the master_key_id change. */
299 ib_mutex_t master_key_id_mutex;
300
301 /** to force correct commit order in binlog */
302 static ulong commit_threads = 0;
303 static mysql_cond_t commit_cond;
304 static mysql_mutex_t commit_cond_m;
305 mysql_cond_t resume_encryption_cond;
306 mysql_mutex_t resume_encryption_cond_m;
307 bool innodb_inited = false;
308
309 3699883976 [[maybe_unused]] static inline bool EQ_CURRENT_THD(THD *thd) {
310 3699883976 return thd == current_thd;
311 }
312
313 static struct handlerton *innodb_hton_ptr;
314
315 static const long AUTOINC_OLD_STYLE_LOCKING = 0;
316 static const long AUTOINC_NEW_STYLE_LOCKING = 1;
317 static const long AUTOINC_NO_LOCKING = 2;
318
319 static long innobase_open_files;
320 static long innobase_autoinc_lock_mode;
321 static ulong innobase_commit_concurrency = 0;
322
323 /* Boolean @@innodb_buffer_pool_in_core_file. */
324 bool srv_buffer_pool_in_core_file = true;
325
326 /** Percentage of the buffer pool to reserve for 'old' blocks.
327 Connected to buf_LRU_old_ratio. */
328 static uint innobase_old_blocks_pct;
329
330 /* The default values for the following char* start-up parameters
331 are determined in innodb_init_params(). */
332
333 static char *innobase_data_home_dir = nullptr;
334 static char *innobase_data_file_path = nullptr;
335 static char *innobase_temp_data_file_path = nullptr;
336 static char *innobase_enable_monitor_counter = nullptr;
337 static char *innobase_disable_monitor_counter = nullptr;
338 static char *innobase_reset_monitor_counter = nullptr;
339 static char *innobase_reset_all_monitor_counter = nullptr;
340 static char *innobase_doublewrite_dir = nullptr;
341
342 static ulong innodb_flush_method;
343
344 /* This variable can be set in the server configure file, specifying
345 stopword table to be used */
346 static char *innobase_server_stopword_table = nullptr;
347
348 /* Below we have boolean-valued start-up parameters, and their default
349 values */
350
351 static bool innobase_rollback_on_timeout = false;
352 static bool innobase_create_status_file = false;
353 bool innobase_stats_on_metadata = true;
354 static bool innodb_optimize_fulltext_only = false;
355
356 static char *innodb_version_str = (char *)INNODB_VERSION_STR;
357
358 static Innodb_data_lock_inspector innodb_data_lock_inspector;
359
360 static const uint MAX_ENCRYPTION_THREADS = 255;
361 extern uint srv_fil_crypt_rotate_key_age;
362 extern uint srv_n_fil_crypt_iops;
363
364 /** Path to the Percona-specific parallel doublewrite buffer (Deprecated) */
365 static char *srv_parallel_doublewrite_path_deprecated = nullptr;
366
367 /** Enable or disable encryption of pages in parallel doublewrite buffer
368 file (Deprecated) */
369 static bool srv_parallel_dblwr_encrypt_deprecated = false;
370
371 /** Note we cannot use rec_format_enum because we do not allow
372 COMPRESSED row format for innodb_default_row_format option. */
373 enum default_row_format_enum {
374 DEFAULT_ROW_FORMAT_REDUNDANT = 0,
375 DEFAULT_ROW_FORMAT_COMPACT = 1,
376 DEFAULT_ROW_FORMAT_DYNAMIC = 2,
377 };
378
379 #if defined(_WIN32) || defined(_WIN64)
380 #include <Windows.h>
381 static double get_mem_GlobalMemoryStatus() {
382 MEMORYSTATUSEX ms;
383 ms.dwLength = sizeof(ms);
384 GlobalMemoryStatusEx(&ms);
385 return (((double)ms.ullTotalPhys) / GB);
386 }
387 #undef get_sys_mem
388 #define get_sys_mem get_mem_GlobalMemoryStatus
389 #else
390 static double get_mem_sysconf() {
391 return (((double)sysconf(_SC_PHYS_PAGES)) *
392 ((double)sysconf(_SC_PAGESIZE) / GB));
393 }
394 #undef get_sys_mem
395 #define get_sys_mem get_mem_sysconf
396 #endif /* defined(_WIN32) || defined(_WIN64) */
397
398 /** Release all acquired services from mysql server. */
399 8462 static void release_plugin_services() {
400
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 8378 times.
8462 if (reg_svc == nullptr) {
401 84 return;
402 }
403
404
1/2
✓ Branch 0 taken 8378 times.
✗ Branch 1 not taken.
8378 if (sysvar_source_svc != nullptr) {
405 using sysvar_source_svc_t = SERVICE_TYPE_NO_CONST(system_variable_source);
406 8378 reg_svc->release(reinterpret_cast<my_h_service>(
407 const_cast<sysvar_source_svc_t *>(sysvar_source_svc)));
408 8378 sysvar_source_svc = nullptr;
409 }
410
411
1/2
✓ Branch 0 taken 8378 times.
✗ Branch 1 not taken.
8378 if (clone_protocol_svc != nullptr) {
412 using clone_protocol_t = SERVICE_TYPE_NO_CONST(clone_protocol);
413 8378 reg_svc->release(reinterpret_cast<my_h_service>(
414 const_cast<clone_protocol_t *>(clone_protocol_svc)));
415 8378 clone_protocol_svc = nullptr;
416 }
417
418 /* Release registry service */
419 8378 mysql_plugin_registry_release(reg_svc);
420 8378 reg_svc = nullptr;
421 }
422
423 /** Acquire required services from mysql server. */
424 9734 static void acquire_plugin_services() {
425 /* Acquire mysql_server's registry service */
426
1/2
✓ Branch 0 taken 9734 times.
✗ Branch 1 not taken.
9734 reg_svc = mysql_plugin_registry_acquire();
427
428
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9734 times.
9734 if (reg_svc == nullptr) {
429 ib::warn(ER_IB_WRN_FAILED_TO_ACQUIRE_SERVICE, "plugin registry");
430 return;
431 }
432
433 my_h_service service;
434
435 /* Acquire system_variable_source service */
436
2/4
✓ Branch 0 taken 9734 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9734 times.
9734 if (reg_svc->acquire("system_variable_source", &service)) {
437 ib::warn(ER_IB_WRN_FAILED_TO_ACQUIRE_SERVICE, "system_variable_source");
438
439 } else {
440 9734 sysvar_source_svc =
441 reinterpret_cast<SERVICE_TYPE(system_variable_source) *>(service);
442 }
443
444 /* Acquire clone protocol service handle. */
445
2/4
✓ Branch 0 taken 9734 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9734 times.
9734 if (reg_svc->acquire("clone_protocol", &service)) {
446 ib::warn(ER_IB_WRN_FAILED_TO_ACQUIRE_SERVICE, "clone_protocol");
447
448 } else {
449 9734 clone_protocol_svc =
450 reinterpret_cast<SERVICE_TYPE(clone_protocol) *>(service);
451 }
452 }
453
454 /** Return the InnoDB ROW_FORMAT enum value
455 @param[in] row_format row_format from "innodb_default_row_format"
456 @return InnoDB ROW_FORMAT value from rec_format_t enum. */
457 395987 static rec_format_t get_row_format(ulong row_format) {
458
3/4
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 225 times.
✓ Branch 2 taken 395735 times.
✗ Branch 3 not taken.
395987 switch (row_format) {
459 27 case DEFAULT_ROW_FORMAT_REDUNDANT:
460 27 return (REC_FORMAT_REDUNDANT);
461 225 case DEFAULT_ROW_FORMAT_COMPACT:
462 225 return (REC_FORMAT_COMPACT);
463 395735 case DEFAULT_ROW_FORMAT_DYNAMIC:
464 395735 return (REC_FORMAT_DYNAMIC);
465 default:
466 ut_d(ut_error);
467 ut_o(return (REC_FORMAT_DYNAMIC));
468 }
469 }
470
471 /** Note that a transaction has been deregistered.
472 @param[in] trx transaction */
473 static void trx_deregister_from_2pc(trx_t *trx);
474 static ulong innodb_default_row_format = DEFAULT_ROW_FORMAT_DYNAMIC;
475
476 #ifdef UNIV_DEBUG
477 /** Values for --innodb-debug-compress names. */
478 static const char *innodb_debug_compress_names[] = {"none", "zlib", "lz4",
479 "lz4hc", NullS};
480
481 /** Enumeration of --innodb-debug-compress */
482 static TYPELIB innodb_debug_compress_typelib = {
483 array_elements(innodb_debug_compress_names) - 1,
484 "innodb_debug_compress_typelib", innodb_debug_compress_names, nullptr};
485 #endif /* UNIV_DEBUG */
486
487 /** Possible values for system variable "innodb_stats_method". The values
488 are defined the same as its corresponding MyISAM system variable
489 "myisam_stats_method"(see "myisam_stats_method_names"), for better usability */
490 static const char *innodb_stats_method_names[] = {
491 "nulls_equal", "nulls_unequal", "nulls_ignored", NullS};
492
493 /** Used to define an enumerate type of the system variable innodb_stats_method.
494 This is the same as "myisam_stats_method_typelib" */
495 static TYPELIB innodb_stats_method_typelib = {
496 array_elements(innodb_stats_method_names) - 1,
497 "innodb_stats_method_typelib", innodb_stats_method_names, nullptr};
498
499 #endif /* UNIV_HOTBACKUP */
500
501 /** Possible values of the parameter innodb_checksum_algorithm */
502 static const char *innodb_checksum_algorithm_names[] = {
503 "crc32", "strict_crc32", "innodb", "strict_innodb",
504 "none", "strict_none", NullS};
505
506 /** Used to define an enumerate type of the system variable
507 innodb_checksum_algorithm. */
508 static TYPELIB innodb_checksum_algorithm_typelib = {
509 array_elements(innodb_checksum_algorithm_names) - 1,
510 "innodb_checksum_algorithm_typelib", innodb_checksum_algorithm_names,
511 nullptr};
512
513 #ifndef UNIV_HOTBACKUP
514 /** Names of allowed values of innodb_flush_method */
515 static const char *innodb_flush_method_names[] = {
516 #ifndef _WIN32 /* See srv_unix_flush_t */
517 "fsync", "O_DSYNC", "littlesync", "nosync", "O_DIRECT", "O_DIRECT_NO_FSYNC",
518 #else /* _WIN32; see srv_win_flush_t */
519 "unbuffered", "normal",
520 #endif
521 NullS};
522
523 /** Enumeration of innodb_flush_method */
524 static TYPELIB innodb_flush_method_typelib = {
525 array_elements(innodb_flush_method_names) - 1,
526 "innodb_flush_method_typelib", innodb_flush_method_names, nullptr};
527
528 /** Possible values for system variable "innodb_cleaner_lsn_age_factor". */
529 static const char *innodb_cleaner_lsn_age_factor_names[] = {
530 "legacy", "high_checkpoint", NullS};
531
532 /** Enumeration for innodb_cleaner_lsn_age_factor. */
533 static TYPELIB innodb_cleaner_lsn_age_factor_typelib = {
534 array_elements(innodb_cleaner_lsn_age_factor_names) - 1,
535 "innodb_cleaner_lsn_age_factor_typelib",
536 innodb_cleaner_lsn_age_factor_names, nullptr};
537
538 /** Possible values for system variable "innodb_empty_free_list_algorithm". */
539 static const char *innodb_empty_free_list_algorithm_names[] = {
540 "legacy", "backoff", NullS};
541
542 /** Enumeration for innodb_empty_free_list_algorithm. */
543 static TYPELIB innodb_empty_free_list_algorithm_typelib = {
544 array_elements(innodb_empty_free_list_algorithm_names) - 1,
545 "innodb_empty_free_list_algorithm_typelib",
546 innodb_empty_free_list_algorithm_names, nullptr};
547
548 /** Possible values for system variable "innodb_default_row_format". */
549 static const char *innodb_default_row_format_names[] = {"redundant", "compact",
550 "dynamic", NullS};
551
552 /** Used to define an enumerate type of the system variable
553 innodb_default_row_format. */
554 static TYPELIB innodb_default_row_format_typelib = {
555 array_elements(innodb_default_row_format_names) - 1,
556 "innodb_default_row_format_typelib", innodb_default_row_format_names,
557 nullptr};
558
559 /** Possible values for system variable "innodb_doublewrite".
560 @note: If you change order or add new values, please update dblwr::mode_t. */
561 static const char *innodb_doublewrite_names[] = {
562 "OFF", "ON", "DETECT_ONLY", "DETECT_AND_RECOVER", "FALSE", "TRUE", NullS};
563
564 /** Used to define an enumerate type of the system variable
565 innodb_default_row_format. */
566 static TYPELIB innodb_doublewrite_typelib = {
567 array_elements(innodb_doublewrite_names) - 1, "innodb_doublewrite_typelib",
568 innodb_doublewrite_names, nullptr};
569
570 #else /* !UNIV_HOTBACKUP */
571
572 /** Returns the name of the checksum algorithm corresponding to the
573 algorithm id given by "algo_enum" parameter.
574 @param[in] algo_enum algorithm enumerator
575 @return C-string algorithm name */
576 const char *meb_get_checksum_algorithm_name(
577 srv_checksum_algorithm_t algo_enum) {
578 return (get_type(&innodb_checksum_algorithm_typelib, algo_enum));
579 }
580
581 /** Retrieves the enum corresponding to the checksum algorithm
582 name specified by algo_name. If the call succeeds, returns
583 true and checksum algorithm enum is returned in algo_enum.
584 @param[in] algo_name algorithm name
585 @param[out] algo_enum algorithm enumerator
586 @retval true if successful
587 @retval false if algorithn name not found */
588 bool meb_get_checksum_algorithm_enum(const char *algo_name,
589 srv_checksum_algorithm_t &algo_enum) {
590 int type =
591 find_type(algo_name, &innodb_checksum_algorithm_typelib, FIND_TYPE_BASIC);
592 if (type <= 0) {
593 /** Invalid algorithm name */
594 return false;
595 } else {
596 algo_enum = srv_checksum_algorithm_t(type - 1);
597 }
598
599 return true;
600 }
601 #endif /* !UNIV_HOTBACKUP */
602
603 static const char *sys_tablespace_encrypt_names[] = {
604 "OFF", "ON", "RE_ENCRYPTING_TO_KEYRING", NullS};
605 static TYPELIB sys_tablespace_encrypt_typelib = {
606 array_elements(sys_tablespace_encrypt_names) - 1,
607 "sys_tablespace_encrypt_typelib", sys_tablespace_encrypt_names, nullptr};
608
609 #ifndef UNIV_HOTBACKUP
610 /* The following counter is used to convey information to InnoDB
611 about server activity: in case of normal DML ops it is not
612 sensible to call srv_active_wake_master_thread after each
613 operation, we only do it every INNOBASE_WAKE_INTERVAL'th step. */
614
615 constexpr uint32_t INNOBASE_WAKE_INTERVAL = 32;
616 static ulong innobase_active_counter = 0;
617
618 static hash_table_t *innobase_open_tables;
619
620 /** Array of data files of the system tablespace */
621 static std::vector<Plugin_tablespace::Plugin_tablespace_file *,
622 ut::allocator<Plugin_tablespace::Plugin_tablespace_file *>>
623 innobase_sys_files;
624
625 /** Allowed values of innodb_change_buffering */
626 static const char *innodb_change_buffering_names[] = {
627 "none", /* IBUF_USE_NONE */
628 "inserts", /* IBUF_USE_INSERT */
629 "deletes", /* IBUF_USE_DELETE_MARK */
630 "changes", /* IBUF_USE_INSERT_DELETE_MARK */
631 "purges", /* IBUF_USE_DELETE */
632 "all", /* IBUF_USE_ALL */
633 NullS};
634
635 /** Enumeration of innodb_change_buffering */
636 static TYPELIB innodb_change_buffering_typelib = {
637 array_elements(innodb_change_buffering_names) - 1,
638 "innodb_change_buffering_typelib", innodb_change_buffering_names, nullptr};
639
640 /** Retrieve the FTS Relevance Ranking result for doc with doc_id
641 of m_prebuilt->fts_doc_id
642 @param[in,out] fts_hdl FTS handler
643 @return the relevance ranking value */
644 static float innobase_fts_retrieve_ranking(FT_INFO *fts_hdl);
645 /** Free the memory for the FTS handler
646 @param[in,out] fts_hdl FTS handler */
647 static void innobase_fts_close_ranking(FT_INFO *fts_hdl);
648
649 /** Find and Retrieve the FTS Relevance Ranking result for doc with doc_id
650 of m_prebuilt->fts_doc_id
651 @param[in,out] fts_hdl FTS handler
652 @return the relevance ranking value */
653 static float innobase_fts_find_ranking(FT_INFO *fts_hdl, uchar *, uint);
654
655 /* Call back function array defined by MySQL and used to
656 retrieve FTS results. */
657 const struct _ft_vft ft_vft_result = {nullptr, innobase_fts_find_ranking,
658 innobase_fts_close_ranking,
659 innobase_fts_retrieve_ranking, nullptr};
660
661 /** @return version of the extended FTS API */
662 static uint innobase_fts_get_version() {
663 /* Currently this doesn't make much sense as returning
664 HA_CAN_FULLTEXT_EXT automatically mean this version is supported.
665 This supposed to ease future extensions. */
666 return (2);
667 }
668
669 /** @return Which part of the extended FTS API is supported */
670 163 static ulonglong innobase_fts_flags() {
671 163 return (FTS_ORDERED_RESULT | FTS_DOCID_IN_RESULT);
672 }
673
674 /** Find and Retrieve the FTS doc_id for the current result row
675 @param[in,out] fts_hdl FTS handler
676 @return the document ID */
677 static ulonglong innobase_fts_retrieve_docid(FT_INFO_EXT *fts_hdl);
678
679 /** Find and retrieve the size of the current result
680 @param[in,out] fts_hdl FTS handler
681 @return number of matching rows */
682 152 static ulonglong innobase_fts_count_matches(
683 FT_INFO_EXT *fts_hdl) /*!< in: FTS handler */
684 {
685 152 NEW_FT_INFO *handle = reinterpret_cast<NEW_FT_INFO *>(fts_hdl);
686
687
2/2
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 15 times.
152 if (handle->ft_result->rankings_by_id != nullptr) {
688 137 return (rbt_size(handle->ft_result->rankings_by_id));
689 } else {
690 15 return (0);
691 }
692 }
693
694 const struct _ft_vft_ext ft_vft_ext_result = {
695 innobase_fts_get_version, innobase_fts_flags, innobase_fts_retrieve_docid,
696 innobase_fts_count_matches};
697
698 #ifdef HAVE_PSI_INTERFACE
699 #define PSI_KEY(n, flag, volatility, doc) \
700 { &(n##_key.m_value), #n, flag, volatility, doc }
701 #define PSI_MEMORY_KEY(n, flag, volatility, doc) \
702 { &(n##_key), #n, flag, volatility, doc }
703 #define PSI_MUTEX_KEY(n, flag, volatility, doc) \
704 { &(n##_key.m_value), #n, flag, volatility, doc }
705 /* All RWLOCK used in Innodb are SX-locks */
706 #define PSI_RWLOCK_KEY(n, volatility, doc) \
707 { &n##_key.m_value, #n, PSI_FLAG_RWLOCK_SX, volatility, doc }
708 #define PSI_THREAD_KEY(n, osn, flag, volatility, doc) \
709 { &(n##_key.m_value), #n, osn, flag, volatility, doc }
710
711 /* Keys to register pthread mutexes/cond in the current file with
712 performance schema */
713 static mysql_pfs_key_t innobase_share_mutex_key;
714 static mysql_pfs_key_t commit_cond_mutex_key;
715 static mysql_pfs_key_t commit_cond_key;
716 mysql_pfs_key_t resume_encryption_cond_mutex_key;
717 mysql_pfs_key_t resume_encryption_cond_key;
718
719 static PSI_mutex_info all_pthread_mutexes[] = {
720 PSI_MUTEX_KEY(commit_cond_mutex, 0, 0, PSI_DOCUMENT_ME),
721 PSI_MUTEX_KEY(innobase_share_mutex, 0, 0, PSI_DOCUMENT_ME),
722 PSI_MUTEX_KEY(resume_encryption_cond_mutex, 0, 0, PSI_DOCUMENT_ME)};
723
724 static PSI_cond_info all_innodb_conds[] = {
725 PSI_KEY(commit_cond, 0, 0, PSI_DOCUMENT_ME),
726 PSI_KEY(resume_encryption_cond, 0, 0, PSI_DOCUMENT_ME)};
727
728 #ifdef UNIV_PFS_MEMORY
729 /* pfs keys related to memory that is performance schema instrumented
730 when "UNIV_PFS_MEMORY" is defined */
731 static PSI_memory_info pfs_instrumented_innodb_memory[] = {
732 PSI_MEMORY_KEY(log_buffer_memory, 0, 0, "Redo log buffer")};
733 #endif /* UNIV_PFS_MEMORY */
734
735 #ifdef UNIV_PFS_MUTEX
736 /* all_innodb_mutexes array contains mutexes that are
737 performance schema instrumented if "UNIV_PFS_MUTEX"
738 is defined */
739 static PSI_mutex_info all_innodb_mutexes[] = {
740 PSI_MUTEX_KEY(autoinc_mutex, 0, 0, PSI_DOCUMENT_ME),
741 PSI_MUTEX_KEY(autoinc_persisted_mutex, 0, 0, PSI_DOCUMENT_ME),
742 #ifndef PFS_SKIP_BUFFER_MUTEX_RWLOCK
743 PSI_MUTEX_KEY(buffer_block_mutex, 0, 0, PSI_DOCUMENT_ME),
744 #endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */
745 PSI_MUTEX_KEY(buf_pool_chunks_mutex, 0, 0, PSI_DOCUMENT_ME),
746 PSI_MUTEX_KEY(buf_pool_flush_state_mutex, 0, 0, PSI_DOCUMENT_ME),
747 PSI_MUTEX_KEY(buf_pool_LRU_list_mutex, 0, 0, PSI_DOCUMENT_ME),
748 PSI_MUTEX_KEY(buf_pool_free_list_mutex, 0, 0, PSI_DOCUMENT_ME),
749 PSI_MUTEX_KEY(buf_pool_zip_free_mutex, 0, 0, PSI_DOCUMENT_ME),
750 PSI_MUTEX_KEY(buf_pool_zip_hash_mutex, 0, 0, PSI_DOCUMENT_ME),
751 PSI_MUTEX_KEY(buf_pool_zip_mutex, 0, 0, PSI_DOCUMENT_ME),
752 PSI_MUTEX_KEY(clone_snapshot_mutex, 0, 0, PSI_DOCUMENT_ME),
753 PSI_MUTEX_KEY(clone_sys_mutex, 0, 0, PSI_DOCUMENT_ME),
754 PSI_MUTEX_KEY(clone_task_mutex, 0, 0, PSI_DOCUMENT_ME),
755 PSI_MUTEX_KEY(ddl_autoinc_mutex, 0, 0, PSI_DOCUMENT_ME),
756 PSI_MUTEX_KEY(dict_foreign_err_mutex, 0, 0, PSI_DOCUMENT_ME),
757 PSI_MUTEX_KEY(dict_persist_dirty_tables_mutex, 0, 0, PSI_DOCUMENT_ME),
758 PSI_MUTEX_KEY(dict_sys_mutex, 0, 0, PSI_DOCUMENT_ME),
759 PSI_MUTEX_KEY(dict_table_mutex, 0, 0, PSI_DOCUMENT_ME),
760 PSI_MUTEX_KEY(parser_mutex, 0, 0, PSI_DOCUMENT_ME),
761 PSI_MUTEX_KEY(recalc_pool_mutex, 0, 0, PSI_DOCUMENT_ME),
762 PSI_MUTEX_KEY(fil_system_mutex, 0, 0, PSI_DOCUMENT_ME),
763 PSI_MUTEX_KEY(file_open_mutex, 0, 0, PSI_DOCUMENT_ME),
764 PSI_MUTEX_KEY(flush_list_mutex, 0, 0, PSI_DOCUMENT_ME),
765 PSI_MUTEX_KEY(fts_bg_threads_mutex, 0, 0, PSI_DOCUMENT_ME),
766 PSI_MUTEX_KEY(fts_delete_mutex, 0, 0, PSI_DOCUMENT_ME),
767 PSI_MUTEX_KEY(fts_optimize_mutex, 0, 0, PSI_DOCUMENT_ME),
768 PSI_MUTEX_KEY(fts_doc_id_mutex, 0, 0, PSI_DOCUMENT_ME),
769 PSI_MUTEX_KEY(fts_pll_tokenize_mutex, 0, 0, PSI_DOCUMENT_ME),
770 PSI_MUTEX_KEY(hash_table_mutex, 0, 0, PSI_DOCUMENT_ME),
771 PSI_MUTEX_KEY(ibuf_bitmap_mutex, 0, 0, PSI_DOCUMENT_ME),
772 PSI_MUTEX_KEY(ibuf_mutex, 0, 0, PSI_DOCUMENT_ME),
773 PSI_MUTEX_KEY(ibuf_pessimistic_insert_mutex, 0, 0, PSI_DOCUMENT_ME),
774 PSI_MUTEX_KEY(lock_free_hash_mutex, 0, 0, PSI_DOCUMENT_ME),
775 PSI_MUTEX_KEY(log_limits_mutex, 0, 0, PSI_DOCUMENT_ME),
776 PSI_MUTEX_KEY(log_files_mutex, 0, 0, PSI_DOCUMENT_ME),
777 PSI_MUTEX_KEY(log_checkpointer_mutex, 0, 0, PSI_DOCUMENT_ME),
778 PSI_MUTEX_KEY(log_closer_mutex, 0, 0, PSI_DOCUMENT_ME),
779 PSI_MUTEX_KEY(log_writer_mutex, 0, 0, PSI_DOCUMENT_ME),
780 PSI_MUTEX_KEY(log_flusher_mutex, 0, 0, PSI_DOCUMENT_ME),
781 PSI_MUTEX_KEY(log_write_notifier_mutex, 0, 0, PSI_DOCUMENT_ME),
782 PSI_MUTEX_KEY(log_flush_notifier_mutex, 0, 0, PSI_DOCUMENT_ME),
783 PSI_MUTEX_KEY(log_sys_arch_mutex, 0, 0, PSI_DOCUMENT_ME),
784 PSI_MUTEX_KEY(log_cmdq_mutex, 0, 0, PSI_DOCUMENT_ME),
785 PSI_MUTEX_KEY(log_sn_mutex, 0, 0, PSI_DOCUMENT_ME),
786 PSI_MUTEX_KEY(mutex_list_mutex, 0, 0, PSI_DOCUMENT_ME),
787 PSI_MUTEX_KEY(page_sys_arch_mutex, 0, 0, PSI_DOCUMENT_ME),
788 PSI_MUTEX_KEY(page_sys_arch_oper_mutex, 0, 0, PSI_DOCUMENT_ME),
789 PSI_MUTEX_KEY(page_sys_arch_client_mutex, 0, 0, PSI_DOCUMENT_ME),
790 PSI_MUTEX_KEY(page_zip_stat_per_index_mutex, 0, 0, PSI_DOCUMENT_ME),
791 PSI_MUTEX_KEY(page_cleaner_mutex, 0, 0, PSI_DOCUMENT_ME),
792 PSI_MUTEX_KEY(parallel_read_mutex, 0, 0, PSI_DOCUMENT_ME),
793 PSI_MUTEX_KEY(dblwr_mutex, 0, 0, PSI_DOCUMENT_ME),
794 PSI_MUTEX_KEY(purge_sys_pq_mutex, 0, 0, PSI_DOCUMENT_ME),
795 PSI_MUTEX_KEY(recv_sys_mutex, 0, 0, PSI_DOCUMENT_ME),
796 PSI_MUTEX_KEY(recv_writer_mutex, 0, 0, PSI_DOCUMENT_ME),
797 PSI_MUTEX_KEY(temp_space_rseg_mutex, 0, 0, PSI_DOCUMENT_ME),
798 PSI_MUTEX_KEY(undo_space_rseg_mutex, 0, 0, PSI_DOCUMENT_ME),
799 PSI_MUTEX_KEY(trx_sys_rseg_mutex, 0, 0, PSI_DOCUMENT_ME),
800 #ifdef UNIV_DEBUG
801 PSI_MUTEX_KEY(rw_lock_debug_mutex, 0, 0, PSI_DOCUMENT_ME),
802 #endif /* UNIV_DEBUG */
803 PSI_MUTEX_KEY(rw_lock_list_mutex, 0, 0, PSI_DOCUMENT_ME),
804 PSI_MUTEX_KEY(rw_lock_mutex, 0, 0, PSI_DOCUMENT_ME),
805 PSI_MUTEX_KEY(srv_innodb_monitor_mutex, 0, 0, PSI_DOCUMENT_ME),
806 PSI_MUTEX_KEY(srv_misc_tmpfile_mutex, 0, 0, PSI_DOCUMENT_ME),
807 PSI_MUTEX_KEY(srv_monitor_file_mutex, 0, 0, PSI_DOCUMENT_ME),
808 #ifdef UNIV_DEBUG
809 PSI_MUTEX_KEY(sync_thread_mutex, 0, 0, PSI_DOCUMENT_ME),
810 #endif /* UNIV_DEBUG */
811 PSI_MUTEX_KEY(trx_undo_mutex, 0, 0, PSI_DOCUMENT_ME),
812 PSI_MUTEX_KEY(trx_pool_mutex, 0, 0, PSI_DOCUMENT_ME),
813 PSI_MUTEX_KEY(trx_pool_manager_mutex, 0, 0, PSI_DOCUMENT_ME),
814 PSI_MUTEX_KEY(temp_pool_manager_mutex, 0, 0, PSI_DOCUMENT_ME),
815 PSI_MUTEX_KEY(srv_sys_mutex, 0, 0, PSI_DOCUMENT_ME),
816 PSI_MUTEX_KEY(lock_sys_page_mutex, 0, 0, PSI_DOCUMENT_ME),
817 PSI_MUTEX_KEY(lock_sys_table_mutex, 0, 0, PSI_DOCUMENT_ME),
818 PSI_MUTEX_KEY(lock_wait_mutex, 0, 0, PSI_DOCUMENT_ME),
819 PSI_MUTEX_KEY(trx_mutex, 0, 0, PSI_DOCUMENT_ME),
820 PSI_MUTEX_KEY(srv_threads_mutex, 0, 0, PSI_DOCUMENT_ME),
821 #ifndef PFS_SKIP_EVENT_MUTEX
822 PSI_MUTEX_KEY(event_mutex, 0, 0, PSI_DOCUMENT_ME),
823 PSI_MUTEX_KEY(event_manager_mutex, 0, 0, PSI_DOCUMENT_ME),
824 #endif /* PFS_SKIP_EVENT_MUTEX */
825 PSI_MUTEX_KEY(rtr_active_mutex, 0, 0, PSI_DOCUMENT_ME),
826 PSI_MUTEX_KEY(rtr_match_mutex, 0, 0, PSI_DOCUMENT_ME),
827 PSI_MUTEX_KEY(rtr_path_mutex, 0, 0, PSI_DOCUMENT_ME),
828 PSI_MUTEX_KEY(rtr_ssn_mutex, 0, 0, PSI_DOCUMENT_ME),
829 PSI_MUTEX_KEY(trx_sys_mutex, 0, 0, PSI_DOCUMENT_ME),
830 PSI_MUTEX_KEY(trx_sys_shard_mutex, 0, 0, PSI_DOCUMENT_ME),
831 PSI_MUTEX_KEY(trx_sys_serialisation_mutex, 0, 0, PSI_DOCUMENT_ME),
832 PSI_MUTEX_KEY(zip_pad_mutex, 0, 0, PSI_DOCUMENT_ME),
833 PSI_MUTEX_KEY(master_key_id_mutex, 0, 0, PSI_DOCUMENT_ME),
834 PSI_MUTEX_KEY(sync_array_mutex, 0, 0, PSI_DOCUMENT_ME),
835 PSI_MUTEX_KEY(row_drop_list_mutex, 0, 0, PSI_DOCUMENT_ME)};
836 #endif /* UNIV_PFS_MUTEX */
837
838 #ifdef UNIV_PFS_RWLOCK
839 /* all_innodb_rwlocks array contains rwlocks that are
840 performance schema instrumented if "UNIV_PFS_RWLOCK"
841 is defined */
842 static PSI_rwlock_info all_innodb_rwlocks[] = {
843 PSI_RWLOCK_KEY(btr_search_latch, 0, PSI_DOCUMENT_ME),
844 #ifndef PFS_SKIP_BUFFER_MUTEX_RWLOCK
845 PSI_RWLOCK_KEY(buf_block_lock, 0, PSI_DOCUMENT_ME),
846 #endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */
847 #ifdef UNIV_DEBUG
848 PSI_RWLOCK_KEY(buf_block_debug_latch, 0, PSI_DOCUMENT_ME),
849 #endif /* UNIV_DEBUG */
850 PSI_RWLOCK_KEY(dict_operation_lock, 0, PSI_DOCUMENT_ME),
851 PSI_RWLOCK_KEY(fil_space_latch, 0, PSI_DOCUMENT_ME),
852 PSI_RWLOCK_KEY(log_sn_lock, 0, PSI_DOCUMENT_ME),
853 PSI_RWLOCK_KEY(undo_spaces_lock, 0, PSI_DOCUMENT_ME),
854 PSI_RWLOCK_KEY(rsegs_lock, 0, PSI_DOCUMENT_ME),
855 PSI_RWLOCK_KEY(lock_sys_global_rw_lock, 0, PSI_DOCUMENT_ME),
856 PSI_RWLOCK_KEY(fts_cache_rw_lock, 0, PSI_DOCUMENT_ME),
857 PSI_RWLOCK_KEY(fts_cache_init_rw_lock, 0, PSI_DOCUMENT_ME),
858 PSI_RWLOCK_KEY(trx_i_s_cache_lock, 0, PSI_DOCUMENT_ME),
859 PSI_RWLOCK_KEY(trx_purge_latch, 0, PSI_DOCUMENT_ME),
860 PSI_RWLOCK_KEY(index_tree_rw_lock, 0, PSI_DOCUMENT_ME),
861 PSI_RWLOCK_KEY(index_online_log, 0, PSI_DOCUMENT_ME),
862 PSI_RWLOCK_KEY(dict_table_stats, 0, PSI_DOCUMENT_ME),
863 PSI_RWLOCK_KEY(hash_table_locks, 0, PSI_DOCUMENT_ME),
864 };
865 #endif /* UNIV_PFS_RWLOCK */
866
867 #ifdef UNIV_PFS_THREAD
868 /* all_innodb_threads array contains threads that are
869 performance schema instrumented if "UNIV_PFS_THREAD"
870 is defined */
871 static PSI_thread_info all_innodb_threads[] = {
872 PSI_THREAD_KEY(log_archiver_thread, "ib_log_arch", PSI_FLAG_SINGLETON, 0,
873 PSI_DOCUMENT_ME),
874 PSI_THREAD_KEY(page_archiver_thread, "ib_page_arch", PSI_FLAG_SINGLETON, 0,
875 PSI_DOCUMENT_ME),
876 PSI_THREAD_KEY(buf_dump_thread, "ib_buf_dump", PSI_FLAG_SINGLETON, 0,
877 PSI_DOCUMENT_ME),
878 PSI_THREAD_KEY(clone_ddl_thread, "ib_clone_ddl", PSI_FLAG_SINGLETON, 0,
879 PSI_DOCUMENT_ME),
880 PSI_THREAD_KEY(clone_gtid_thread, "ib_clone_gtid", PSI_FLAG_SINGLETON, 0,
881 PSI_DOCUMENT_ME),
882 PSI_THREAD_KEY(ddl_thread, "ib_ddl", 0, 0, PSI_DOCUMENT_ME),
883 PSI_THREAD_KEY(dict_stats_thread, "ib_dict_stats", PSI_FLAG_SINGLETON, 0,
884 PSI_DOCUMENT_ME),
885 PSI_THREAD_KEY(io_handler_thread, "ib_io_handler", PSI_FLAG_SINGLETON, 0,
886 PSI_DOCUMENT_ME),
887 PSI_THREAD_KEY(io_ibuf_thread, "ib_io_ibuf", PSI_FLAG_SINGLETON, 0,
888 PSI_DOCUMENT_ME),
889 PSI_THREAD_KEY(io_log_thread, "ib_io_log", PSI_FLAG_SINGLETON, 0,
890 PSI_DOCUMENT_ME),
891 PSI_THREAD_KEY(io_read_thread, "ib_io_rd", 0, 0, PSI_DOCUMENT_ME),
892 PSI_THREAD_KEY(io_write_thread, "ib_io_wr", 0, 0, PSI_DOCUMENT_ME),
893 PSI_THREAD_KEY(buf_resize_thread, "ib_buf_resize", PSI_FLAG_SINGLETON, 0,
894 PSI_DOCUMENT_ME),
895 PSI_THREAD_KEY(log_files_governor_thread, "ib_log_files_g",
896 PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME),
897 PSI_THREAD_KEY(log_writer_thread, "ib_log_writer", PSI_FLAG_SINGLETON, 0,
898 PSI_DOCUMENT_ME),
899 PSI_THREAD_KEY(log_checkpointer_thread, "ib_log_checkpt",
900 PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME),
901 PSI_THREAD_KEY(log_flusher_thread, "ib_log_flush", PSI_FLAG_SINGLETON, 0,
902 PSI_DOCUMENT_ME),
903 PSI_THREAD_KEY(log_write_notifier_thread, "ib_log_wr_notif",
904 PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME),
905 PSI_THREAD_KEY(log_flush_notifier_thread, "ib_log_fl_notif",
906 PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME),
907 PSI_THREAD_KEY(buf_lru_manager_thread, "ib_buf_lru", 0, 0,
908 PSI_DOCUMENT_ME),
909 PSI_THREAD_KEY(recv_writer_thread, "ib_recv_write", PSI_FLAG_SINGLETON, 0,
910 PSI_DOCUMENT_ME),
911 PSI_THREAD_KEY(srv_error_monitor_thread, "ib_srv_err",
912 PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME),
913 PSI_THREAD_KEY(srv_lock_timeout_thread, "ib_srv_lock_to",
914 PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME),
915 PSI_THREAD_KEY(srv_master_thread, "ib_src_main", PSI_FLAG_SINGLETON, 0,
916 PSI_DOCUMENT_ME),
917 PSI_THREAD_KEY(srv_monitor_thread, "ib_srv_mon", PSI_FLAG_SINGLETON, 0,
918 PSI_DOCUMENT_ME),
919 PSI_THREAD_KEY(srv_purge_thread, "ib_srv_purge", PSI_FLAG_SINGLETON, 0,
920 PSI_DOCUMENT_ME),
921 PSI_THREAD_KEY(srv_worker_thread, "ib_srv_wkr", 0, 0, PSI_DOCUMENT_ME),
922 PSI_THREAD_KEY(trx_recovery_rollback_thread, "ib_tx_recov", 0, 0,
923 PSI_DOCUMENT_ME),
924 PSI_THREAD_KEY(page_flush_thread, "ib_pg_flush", 0, 0, PSI_DOCUMENT_ME),
925 PSI_THREAD_KEY(page_flush_coordinator_thread, "ib_pg_flush_co",
926 PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME),
927 PSI_THREAD_KEY(fts_optimize_thread, "ib_fts_opt", PSI_FLAG_SINGLETON, 0,
928 PSI_DOCUMENT_ME),
929 PSI_THREAD_KEY(fts_parallel_merge_thread, "ib_fts_merge", 0, 0,
930 PSI_DOCUMENT_ME),
931 PSI_THREAD_KEY(fts_parallel_tokenization_thread, "ib_fts_token", 0, 0,
932 PSI_DOCUMENT_ME),
933 PSI_THREAD_KEY(srv_ts_alter_encrypt_thread, "ib_ts_encrypt",
934 PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME),
935 PSI_THREAD_KEY(parallel_read_thread, "ib_par_rd", 0, 0, PSI_DOCUMENT_ME),
936 PSI_THREAD_KEY(parallel_rseg_init_thread, "ib_par_rseg", 0, 0,
937 PSI_DOCUMENT_ME),
938 PSI_THREAD_KEY(meb::redo_log_archive_consumer_thread, "ib_meb_rl",
939 PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME)};
940 #endif /* UNIV_PFS_THREAD */
941
942 #ifdef UNIV_PFS_IO
943 /* all_innodb_files array contains the type of files that are
944 performance schema instrumented if "UNIV_PFS_IO" is defined */
945 static PSI_file_info all_innodb_files[] = {
946 PSI_KEY(innodb_dblwr_file, 0, 0, PSI_DOCUMENT_ME),
947 PSI_KEY(innodb_tablespace_open_file, 0, 0, PSI_DOCUMENT_ME),
948 PSI_KEY(innodb_data_file, 0, 0, PSI_DOCUMENT_ME),
949 PSI_KEY(innodb_log_file, 0, 0, PSI_DOCUMENT_ME),
950 PSI_KEY(innodb_bmp_file, 0, 0, PSI_DOCUMENT_ME),
951 PSI_KEY(innodb_temp_file, 0, 0, PSI_DOCUMENT_ME),
952 PSI_KEY(innodb_arch_file, 0, 0, PSI_DOCUMENT_ME),
953 PSI_KEY(innodb_clone_file, 0, 0, PSI_DOCUMENT_ME),
954 PSI_KEY(meb::redo_log_archive_file, 0, 0, PSI_DOCUMENT_ME)};
955 #endif /* UNIV_PFS_IO */
956 #endif /* HAVE_PSI_INTERFACE */
957
958 13 static int default_encryption_key_id_validate(
959 /*=================================*/
960 THD *thd, /*!< in: thread handle */
961 SYS_VAR *var, /*!< in: pointer to system
962 variable */
963 void *save, /*!< out: immediate result
964 for update function */
965 st_mysql_value *value) /*!< in: incoming string */ {
966 long long intbuf;
967
968
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 DBUG_ENTER("default_encryption_key_id_validate");
969
970
2/4
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
13 if (value->val_int(value, &intbuf)) {
971 /* The value is NULL. That is invalid. */
972 DBUG_RETURN(1);
973 }
974
975 13 bool is_val_fixed = false;
976 13 auto key_id = intbuf;
977
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 10 times.
13 if (intbuf < 0) {
978 3 key_id = 0;
979 3 is_val_fixed = true;
980
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7 times.
10 } else if (intbuf >= UINT_MAX32) {
981 3 key_id = UINT_MAX32 - 1;
982 3 is_val_fixed = true;
983 }
984
985
2/4
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
13 if (throw_bounds_warning(thd, "innodb_encryption_key_id", is_val_fixed,
986 intbuf)) {
987 DBUG_RETURN(1);
988 }
989
990
2/4
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
13 if (!Encryption::tablespace_key_exists_or_create_new_one_if_does_not_exist(
991 static_cast<uint>(key_id), server_uuid)) {
992 push_warning_printf(thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED,
993 "InnoDB: cannot enable encryption, "
994 "keyring plugin is not available");
995 DBUG_RETURN(1);
996 }
997
998 13 *reinterpret_cast<ulong *>(save) = static_cast<ulong>(key_id);
999
1000
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 DBUG_RETURN(0);
1001 }
1002
1003 13 static void default_encryption_key_id_update(
1004 THD *thd, // in: thread handle <]
1005 SYS_VAR *var, // in: pointer to
1006 // system variable */
1007 void *var_ptr, // where the
1008 // formal string goes */
1009 const void *save) { // in: immediate result
1010 // from check function
1011 13 *static_cast<ulong *>(var_ptr) = *static_cast<const ulong *>(save);
1012 13 }
1013
1014 static MYSQL_THDVAR_UINT(default_encryption_key_id, PLUGIN_VAR_RQCMDARG,
1015 "Default encryption key id used for table encryption.",
1016 default_encryption_key_id_validate,
1017 default_encryption_key_id_update,
1018 FIL_DEFAULT_ENCRYPTION_KEY, 0, UINT_MAX32 - 1, 0);
1019
1020 418 uint get_global_default_encryption_key_id_value() {
1021 418 return THDVAR(NULL, default_encryption_key_id);
1022 }
1023
1024 static MYSQL_THDVAR_UINT(records_in_range, PLUGIN_VAR_RQCMDARG,
1025 "Used to override the result of records_in_range(). "
1026 "Set to a positive number to override",
1027 NULL, NULL, 0,
1028 /* min */ 0, /* max */ INT_MAX, 0);
1029
1030 static MYSQL_THDVAR_UINT(force_index_records_in_range, PLUGIN_VAR_RQCMDARG,
1031 "Used to override the result of records_in_range() "
1032 "when FORCE INDEX is used.",
1033 NULL, NULL, 0,
1034 /* min */ 0, /* max */ INT_MAX, 0);
1035
1036 39 uint innodb_force_index_records_in_range(THD *thd) {
1037 39 return THDVAR(thd, force_index_records_in_range);
1038 }
1039
1040 23614 uint innodb_records_in_range(THD *thd) { return THDVAR(thd, records_in_range); }
1041
1042 /** Plugin update function to handle validation and then switch the
1043 innodb_doublewrite mode
1044 @param[in] thd thread handle
1045 @param[in] var pointer to system variable
1046 @param[in] var_ptr where the formal string goes
1047 @param[in] save immediate result from check function */
1048 92 static void doublewrite_update(THD *thd [[maybe_unused]],
1049 SYS_VAR *var [[maybe_unused]], void *var_ptr,
1050 const void *save) {
1051 92 ulong new_value = *static_cast<const ulong *>(save);
1052
1053
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 75 times.
92 if (dblwr::Mode::is_enabled_to_disabled(new_value)) {
1054 char msg[FN_REFLEN];
1055
2/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
17 snprintf(msg, sizeof(msg),
1056 "InnoDB: cannot change doublewrite mode to %s if"
1057 " doublewrite is enabled. Please shutdown and"
1058 " change value to %s",
1059 dblwr::Mode::to_string(new_value),
1060 dblwr::Mode::to_string(new_value));
1061
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 my_error(ER_WRONG_ARGUMENTS, MYF(0), msg);
1062 17 return;
1063 }
1064
1065
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 59 times.
75 if (dblwr::Mode::is_disabled_to_enabled(new_value)) {
1066 char msg[FN_REFLEN];
1067
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 snprintf(msg, sizeof(msg),
1068 "InnoDB: cannot change doublewrite mode to %s if"
1069 " doublewrite is disabled. Please shutdown and"
1070 " change value to %s",
1071 dblwr::Mode::to_string(new_value),
1072 dblwr::Mode::to_string(new_value));
1073
1074
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 my_error(ER_WRONG_ARGUMENTS, MYF(0), msg);
1075
1076 16 return;
1077 }
1078
1079
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 35 times.
59 if (dblwr::Mode::is_same(new_value)) {
1080 24 return;
1081 }
1082
1083 /* Handle DETECT_AND_RECOVER to DETECT_ONLY
1084 1. Check if DETECT_ONLY setup is already initalized. If not, intialize
1085 DETECT_ONLY files and structures.
1086 2. Flush the partially filled dblwr buffers. */
1087
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 18 times.
35 if (dblwr::Mode::is_reduced_low(new_value)) {
1088 17 dberr_t err = dblwr::enable_reduced();
1089
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (err != DB_SUCCESS) {
1090 char msg[FN_REFLEN];
1091 snprintf(msg, sizeof(msg),
1092 "InnoDB: cannot change doublewrite mode to %s."
1093 " Please check if doublewrite directory is writable"
1094 " Error code: %d",
1095 dblwr::Mode::to_string(new_value), err);
1096 my_error(ER_WRONG_ARGUMENTS, MYF(0), msg);
1097 return;
1098 }
1099 }
1100
1101 /* Handle DETECT_ONLY to DETECT_AND_RECOVER.
1102 1. Flush partially filled reduced dblwr buffers */
1103 35 dblwr::force_flush_all();
1104
1105 35 *static_cast<ulong *>(var_ptr) = *static_cast<const ulong *>(save);
1106 }
1107
1108 /** Set up InnoDB API callback function array */
1109 /*
1110 Generates array elements which look like:
1111 (ib_cb_t)ib_cursor_open_table,
1112 for each api function.
1113 */
1114 #define INNODB_API_CB_ARRAY_ELEMENT_TRANSFORM(stem) (ib_cb_t) ib_##stem,
1115
1116 static ib_cb_t innodb_api_cb[] = {
1117 FOR_EACH_API_METHOD_NAME_STEM(INNODB_API_CB_ARRAY_ELEMENT_TRANSFORM)};
1118
1119 static int innodb_check_session_admin(THD *thd, SYS_VAR *self, void *save,
1120 struct st_mysql_value *value);
1121
1122 /**Check whether valid argument given to innobase_*_stopword_table.
1123 This function is registered as a callback with MySQL.
1124 @param[in] thd thread handle
1125 @param[in] var pointer to system variable
1126 @param[out] save immediate result for update function
1127 @param[in] value incoming string
1128 @return 0 for valid stopword table */
1129 static int innodb_stopword_table_validate(THD *thd, SYS_VAR *var, void *save,
1130 struct st_mysql_value *value);
1131
1132 /** Validate passed-in "value" is a valid directory name.
1133 This function is registered as a callback with MySQL.
1134 @param[in,out] thd thread handle
1135 @param[out] save immediate result for update
1136 @param[in] value incoming string
1137 @return 0 for valid name */
1138 17 static int innodb_tmpdir_validate(THD *thd, SYS_VAR *, void *save,
1139 struct st_mysql_value *value) {
1140 char *alter_tmp_dir;
1141 char *innodb_tmp_dir;
1142 char buff[OS_FILE_MAX_PATH];
1143 17 int len = sizeof(buff);
1144 char tmp_abs_path[FN_REFLEN + 2];
1145
1146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 ut_ad(save != nullptr);
1147
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 ut_ad(value != nullptr);
1148
1149
2/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
17 if (check_global_access(thd, FILE_ACL)) {
1150 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
1151 "InnoDB: FILE Permissions required");
1152 *static_cast<const char **>(save) = nullptr;
1153 return (1);
1154 }
1155
1156
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 alter_tmp_dir = (char *)value->val_str(value, buff, &len);
1157
1158
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 8 times.
17 if (!alter_tmp_dir) {
1159 9 *static_cast<const char **>(save) = alter_tmp_dir;
1160 9 return (0);
1161 }
1162
1163
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 if (strlen(alter_tmp_dir) > FN_REFLEN) {
1164
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
1165 "Path length should not exceed %d bytes", FN_REFLEN);
1166 1 *static_cast<const char **>(save) = nullptr;
1167 1 return (1);
1168 }
1169
1170 7 Fil_path::normalize(alter_tmp_dir);
1171
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 my_realpath(tmp_abs_path, alter_tmp_dir, 0);
1172 7 size_t tmp_abs_len = strlen(tmp_abs_path);
1173
1174
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5 times.
7 if (my_access(tmp_abs_path, F_OK)) {
1175
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
1176 "InnoDB: Path doesn't exist.");
1177 2 *static_cast<const char **>(save) = nullptr;
1178 2 return (1);
1179
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 } else if (my_access(tmp_abs_path, R_OK | W_OK)) {
1180 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
1181 "InnoDB: Server doesn't have permission in "
1182 "the given location.");
1183 *static_cast<const char **>(save) = nullptr;
1184 return (1);
1185 }
1186
1187 MY_STAT stat_info_dir;
1188
1189
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 if (my_stat(tmp_abs_path, &stat_info_dir, MYF(0))) {
1190
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if ((stat_info_dir.st_mode & S_IFDIR) != S_IFDIR) {
1191 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
1192 "Given path is not a directory. ");
1193 *static_cast<const char **>(save) = nullptr;
1194 return (1);
1195 }
1196 }
1197
1198
3/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 4 times.
5 if (!is_mysql_datadir_path(tmp_abs_path)) {
1199
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
1200 "InnoDB: Path location should not be same as "
1201 "mysql data directory location.");
1202 1 *static_cast<const char **>(save) = nullptr;
1203 1 return (1);
1204 }
1205
1206 innodb_tmp_dir =
1207
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 static_cast<char *>(thd_memdup(thd, tmp_abs_path, tmp_abs_len + 1));
1208 4 *static_cast<const char **>(save) = innodb_tmp_dir;
1209 4 return (0);
1210 }
1211
1212 /** Empty free list algorithm.
1213 Checks if buffer pool is big enough to enable backoff algorithm.
1214 InnoDB empty free list algorithm backoff requires free pages
1215 from LRU for the best performance.
1216 buf_LRU_buf_pool_running_out cancels query if 1/4 of
1217 buffer pool belongs to LRU or freelist.
1218 At the same time buf_flush_LRU_list_batch
1219 keeps up to BUF_LRU_MIN_LEN in LRU.
1220 In order to avoid deadlock backoff requires buffer pool
1221 to be at least 4*BUF_LRU_MIN_LEN,
1222 but flush peformance is bad because of trashing
1223 and additional BUF_LRU_MIN_LEN pages are requested.
1224 @param[in] algorithm desired algorithm from srv_empty_free_list_t
1225 @param[in] new_buf_pool_sz requested buffer pool size
1226 @return true if it's possible to enable backoff. */
1227 9766 static bool innodb_empty_free_list_algorithm_allowed(
1228 srv_empty_free_list_t algorithm, long long new_buf_pool_sz = 0) {
1229
2/2
✓ Branch 0 taken 9737 times.
✓ Branch 1 taken 29 times.
9766 if (!new_buf_pool_sz) new_buf_pool_sz = srv_buf_pool_size;
1230
1231 9766 const long long buf_pool_pages =
1232 9766 new_buf_pool_sz / srv_page_size / srv_buf_pool_instances;
1233
1234
4/4
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 9732 times.
✓ Branch 2 taken 29 times.
✓ Branch 3 taken 5 times.
9766 return (buf_pool_pages >= BUF_LRU_MIN_LEN * (4 + 1) ||
1235 9766 algorithm != SRV_EMPTY_FREE_LIST_BACKOFF);
1236 }
1237
1238 /** Gets field offset for a field in a table.
1239 @param[in] table MySQL table object
1240 @param[in] field MySQL field object
1241 @return offset */
1242 static inline uint get_field_offset(const TABLE *table, const Field *field);
1243
1244 static MYSQL_THDVAR_BOOL(table_locks, PLUGIN_VAR_OPCMDARG,
1245 "Enable InnoDB locking in LOCK TABLES",
1246 /* check_func */ nullptr, /* update_func */ nullptr,
1247 /* default */ true);
1248
1249 static MYSQL_THDVAR_BOOL(strict_mode, PLUGIN_VAR_OPCMDARG,
1250 "Use strict mode when evaluating create options.",
1251 innodb_check_session_admin, nullptr, true);
1252
1253 static MYSQL_THDVAR_BOOL(ft_enable_stopword,
1254 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_HINTUPDATEABLE,
1255 "Create FTS index with stopword.", nullptr, nullptr,
1256 /* default */ true);
1257
1258 static MYSQL_THDVAR_ULONG(lock_wait_timeout,
1259 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_HINTUPDATEABLE,
1260 "Timeout in seconds an InnoDB transaction may wait "
1261 "for a lock before being rolled back. Values above "
1262 "100000000 disable the timeout.",
1263 nullptr, nullptr, 50, 1, 1024 * 1024 * 1024, 0);
1264
1265 static MYSQL_THDVAR_STR(
1266 ft_user_stopword_table,
1267 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_HINTUPDATEABLE,
1268 "User supplied stopword table name, effective in the session level.",
1269 innodb_stopword_table_validate, nullptr, nullptr);
1270
1271 static MYSQL_THDVAR_STR(tmpdir,
1272 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_MEMALLOC |
1273 PLUGIN_VAR_HINTUPDATEABLE,
1274 "Directory for temporary non-tablespace files.",
1275 innodb_tmpdir_validate, nullptr, nullptr);
1276
1277 static MYSQL_THDVAR_BOOL(ft_ignore_stopwords, PLUGIN_VAR_OPCMDARG,
1278 "Instruct FTS to ignore stopwords.", nullptr, nullptr,
1279 false);
1280
1281 static MYSQL_THDVAR_ULONG(parallel_read_threads, PLUGIN_VAR_RQCMDARG,
1282 "Number of threads to do parallel read.", nullptr,
1283 nullptr, 4, /* Default. */
1284 1, /* Minimum. */
1285 Parallel_reader::MAX_THREADS, /* Maxumum. */
1286 0);
1287
1288 static MYSQL_THDVAR_ULONG(ddl_buffer_size, PLUGIN_VAR_RQCMDARG,
1289 "Maximum size of memory to use (in bytes) for DDL.",
1290 nullptr, nullptr, 1048576, /* Default. */
1291 65536, /* Minimum. */
1292 4294967295, 0); /* Maximum. */
1293
1294 static MYSQL_THDVAR_ULONG(ddl_threads, PLUGIN_VAR_RQCMDARG,
1295 "Maximum number of threads to use for DDL.", nullptr,
1296 nullptr, 4, /* Default. */
1297 1, /* Minimum. */
1298 64, 0); /* Maximum. */
1299
1300 static SHOW_VAR innodb_status_variables[] = {
1301 {"background_log_sync", (char *)&export_vars.innodb_background_log_sync,
1302 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1303 {"buffer_pool_dump_status",
1304 (char *)&export_vars.innodb_buffer_pool_dump_status, SHOW_CHAR,
1305 SHOW_SCOPE_GLOBAL},
1306 {"buffer_pool_load_status",
1307 (char *)&export_vars.innodb_buffer_pool_load_status, SHOW_CHAR,
1308 SHOW_SCOPE_GLOBAL},
1309 {"buffer_pool_resize_status",
1310 (char *)&export_vars.innodb_buffer_pool_resize_status, SHOW_CHAR,
1311 SHOW_SCOPE_GLOBAL},
1312 {"buffer_pool_pages_data",
1313 (char *)&export_vars.innodb_buffer_pool_pages_data, SHOW_LONG,
1314 SHOW_SCOPE_GLOBAL},
1315 {"buffer_pool_bytes_data",
1316 (char *)&export_vars.innodb_buffer_pool_bytes_data, SHOW_LONG,
1317 SHOW_SCOPE_GLOBAL},
1318 {"buffer_pool_pages_dirty",
1319 (char *)&export_vars.innodb_buffer_pool_pages_dirty, SHOW_LONG,
1320 SHOW_SCOPE_GLOBAL},
1321 {"buffer_pool_bytes_dirty",
1322 (char *)&export_vars.innodb_buffer_pool_bytes_dirty, SHOW_LONG,
1323 SHOW_SCOPE_GLOBAL},
1324 {"buffer_pool_pages_flushed",
1325 (char *)&export_vars.innodb_buffer_pool_pages_flushed, SHOW_LONG,
1326 SHOW_SCOPE_GLOBAL},
1327 {"buffer_pool_pages_free",
1328 (char *)&export_vars.innodb_buffer_pool_pages_free, SHOW_LONG,
1329 SHOW_SCOPE_GLOBAL},
1330 #ifdef UNIV_DEBUG
1331 {"buffer_pool_pages_latched",
1332 (char *)&export_vars.innodb_buffer_pool_pages_latched, SHOW_LONG,
1333 SHOW_SCOPE_GLOBAL},
1334 #endif /* UNIV_DEBUG */
1335 {"buffer_pool_pages_LRU_flushed",
1336 (char *)&export_vars.innodb_buffer_pool_pages_LRU_flushed, SHOW_LONG,
1337 SHOW_SCOPE_GLOBAL},
1338 {"buffer_pool_pages_made_not_young",
1339 (char *)&export_vars.innodb_buffer_pool_pages_made_not_young, SHOW_LONG,
1340 SHOW_SCOPE_GLOBAL},
1341 {"buffer_pool_pages_made_young",
1342 (char *)&export_vars.innodb_buffer_pool_pages_made_young, SHOW_LONG,
1343 SHOW_SCOPE_GLOBAL},
1344 {"buffer_pool_pages_misc",
1345 (char *)&export_vars.innodb_buffer_pool_pages_misc, SHOW_LONG,
1346 SHOW_SCOPE_GLOBAL},
1347 {"buffer_pool_pages_old", (char *)&export_vars.innodb_buffer_pool_pages_old,
1348 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1349 {"buffer_pool_pages_total",
1350 (char *)&export_vars.innodb_buffer_pool_pages_total, SHOW_LONG,
1351 SHOW_SCOPE_GLOBAL},
1352 {"buffer_pool_read_ahead_rnd",
1353 (char *)&export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_LONG,
1354 SHOW_SCOPE_GLOBAL},
1355 {"buffer_pool_read_ahead",
1356 (char *)&export_vars.innodb_buffer_pool_read_ahead, SHOW_LONG,
1357 SHOW_SCOPE_GLOBAL},
1358 {"buffer_pool_read_ahead_evicted",
1359 (char *)&export_vars.innodb_buffer_pool_read_ahead_evicted, SHOW_LONG,
1360 SHOW_SCOPE_GLOBAL},
1361 {"buffer_pool_read_requests",
1362 (char *)&export_vars.innodb_buffer_pool_read_requests, SHOW_LONG,
1363 SHOW_SCOPE_GLOBAL},
1364 {"buffer_pool_reads", (char *)&export_vars.innodb_buffer_pool_reads,
1365 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1366 {"buffer_pool_wait_free", (char *)&export_vars.innodb_buffer_pool_wait_free,
1367 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1368 {"buffer_pool_write_requests",
1369 (char *)&export_vars.innodb_buffer_pool_write_requests, SHOW_LONG,
1370 SHOW_SCOPE_GLOBAL},
1371 {"checkpoint_age", (char *)&export_vars.innodb_checkpoint_age, SHOW_LONG,
1372 SHOW_SCOPE_GLOBAL},
1373 {"checkpoint_max_age", (char *)&export_vars.innodb_checkpoint_max_age,
1374 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1375 {"data_fsyncs", (char *)&export_vars.innodb_data_fsyncs, SHOW_LONG,
1376 SHOW_SCOPE_GLOBAL},
1377 {"data_pending_fsyncs", (char *)&export_vars.innodb_data_pending_fsyncs,
1378 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1379 {"data_pending_reads", (char *)&export_vars.innodb_data_pending_reads,
1380 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1381 {"data_pending_writes", (char *)&export_vars.innodb_data_pending_writes,
1382 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1383 {"data_read", (char *)&export_vars.innodb_data_read, SHOW_LONG,
1384 SHOW_SCOPE_GLOBAL},
1385 {"data_reads", (char *)&export_vars.innodb_data_reads, SHOW_LONG,
1386 SHOW_SCOPE_GLOBAL},
1387 {"data_writes", (char *)&export_vars.innodb_data_writes, SHOW_LONG,
1388 SHOW_SCOPE_GLOBAL},
1389 {"data_written", (char *)&export_vars.innodb_data_written, SHOW_LONG,
1390 SHOW_SCOPE_GLOBAL},
1391 {"dblwr_pages_written", (char *)&export_vars.innodb_dblwr_pages_written,
1392 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1393 {"dblwr_writes", (char *)&export_vars.innodb_dblwr_writes, SHOW_LONG,
1394 SHOW_SCOPE_GLOBAL},
1395 {"ibuf_free_list", (char *)&export_vars.innodb_ibuf_free_list, SHOW_LONG,
1396 SHOW_SCOPE_GLOBAL},
1397 {"ibuf_segment_size", (char *)&export_vars.innodb_ibuf_segment_size,
1398 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1399 {"redo_log_read_only", (char *)&export_vars.innodb_redo_log_read_only,
1400 SHOW_BOOL, SHOW_SCOPE_GLOBAL},
1401 {"redo_log_uuid", (char *)&export_vars.innodb_redo_log_uuid, SHOW_LONGLONG,
1402 SHOW_SCOPE_GLOBAL},
1403 {"redo_log_checkpoint_lsn",
1404 (char *)&export_vars.innodb_redo_log_checkpoint_lsn, SHOW_LONGLONG,
1405 SHOW_SCOPE_GLOBAL},
1406 {"redo_log_current_lsn", (char *)&export_vars.innodb_redo_log_current_lsn,
1407 SHOW_LONGLONG, SHOW_SCOPE_GLOBAL},
1408 {"redo_log_flushed_to_disk_lsn",
1409 (char *)&export_vars.innodb_redo_log_flushed_to_disk_lsn, SHOW_LONGLONG,
1410 SHOW_SCOPE_GLOBAL},
1411 {"redo_log_logical_size", (char *)&export_vars.innodb_redo_log_logical_size,
1412 SHOW_LONGLONG, SHOW_SCOPE_GLOBAL},
1413 {"redo_log_physical_size",
1414 (char *)&export_vars.innodb_redo_log_physical_size, SHOW_LONGLONG,
1415 SHOW_SCOPE_GLOBAL},
1416 {"redo_log_capacity_resized",
1417 (char *)&export_vars.innodb_redo_log_capacity_resized, SHOW_LONGLONG,
1418 SHOW_SCOPE_GLOBAL},
1419 {"redo_log_resize_status",
1420 (char *)&export_vars.innodb_redo_log_resize_status, SHOW_CHAR,
1421 SHOW_SCOPE_GLOBAL},
1422 {"log_waits", (char *)&export_vars.innodb_log_waits, SHOW_LONG,
1423 SHOW_SCOPE_GLOBAL},
1424 {"log_write_requests", (char *)&export_vars.innodb_log_write_requests,
1425 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1426 {"log_writes", (char *)&export_vars.innodb_log_writes, SHOW_LONG,
1427 SHOW_SCOPE_GLOBAL},
1428 {"lsn_current", (char *)&export_vars.innodb_lsn_current, SHOW_LONGLONG,
1429 SHOW_SCOPE_GLOBAL},
1430 {"lsn_flushed", (char *)&export_vars.innodb_lsn_flushed, SHOW_LONGLONG,
1431 SHOW_SCOPE_GLOBAL},
1432 {"lsn_last_checkpoint", (char *)&export_vars.innodb_lsn_last_checkpoint,
1433 SHOW_LONGLONG, SHOW_SCOPE_GLOBAL},
1434 {"master_thread_active_loops",
1435 (char *)&export_vars.innodb_master_thread_active_loops, SHOW_LONG,
1436 SHOW_SCOPE_GLOBAL},
1437 {"master_thread_idle_loops",
1438 (char *)&export_vars.innodb_master_thread_idle_loops, SHOW_LONG,
1439 SHOW_SCOPE_GLOBAL},
1440 {"max_trx_id", (char *)&export_vars.innodb_max_trx_id, SHOW_LONGLONG,
1441 SHOW_SCOPE_GLOBAL},
1442 {"oldest_view_low_limit_trx_id",
1443 (char *)&export_vars.innodb_oldest_view_low_limit_trx_id, SHOW_LONGLONG,
1444 SHOW_SCOPE_GLOBAL},
1445 {"os_log_fsyncs", (char *)&export_vars.innodb_os_log_fsyncs, SHOW_LONG,
1446 SHOW_SCOPE_GLOBAL},
1447 {"os_log_pending_fsyncs", (char *)&export_vars.innodb_os_log_pending_fsyncs,
1448 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1449 {"os_log_pending_writes", (char *)&export_vars.innodb_os_log_pending_writes,
1450 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1451 {"os_log_written", (char *)&export_vars.innodb_os_log_written,
1452 SHOW_LONGLONG, SHOW_SCOPE_GLOBAL},
1453 {"page_size", (char *)&export_vars.innodb_page_size, SHOW_LONG,
1454 SHOW_SCOPE_GLOBAL},
1455 {"pages_created", (char *)&export_vars.innodb_pages_created, SHOW_LONG,
1456 SHOW_SCOPE_GLOBAL},
1457 {"pages_read", (char *)&export_vars.innodb_pages_read, SHOW_LONG,
1458 SHOW_SCOPE_GLOBAL},
1459 {"pages0_read", (char *)&export_vars.innodb_page0_read, SHOW_LONG,
1460 SHOW_SCOPE_GLOBAL},
1461 {"pages_written", (char *)&export_vars.innodb_pages_written, SHOW_LONG,
1462 SHOW_SCOPE_GLOBAL},
1463 {"purge_trx_id", (char *)&export_vars.innodb_purge_trx_id, SHOW_LONGLONG,
1464 SHOW_SCOPE_GLOBAL},
1465 {"purge_undo_no", (char *)&export_vars.innodb_purge_undo_no, SHOW_LONGLONG,
1466 SHOW_SCOPE_GLOBAL},
1467 {"redo_log_enabled", (char *)&export_vars.innodb_redo_log_enabled,
1468 SHOW_BOOL, SHOW_SCOPE_GLOBAL},
1469 {"row_lock_current_waits",
1470 (char *)&export_vars.innodb_row_lock_current_waits, SHOW_LONG,
1471 SHOW_SCOPE_GLOBAL},
1472 {"row_lock_time", (char *)&export_vars.innodb_row_lock_time, SHOW_LONGLONG,
1473 SHOW_SCOPE_GLOBAL},
1474 {"row_lock_time_avg", (char *)&export_vars.innodb_row_lock_time_avg,
1475 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1476 {"row_lock_time_max", (char *)&export_vars.innodb_row_lock_time_max,
1477 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1478 {"row_lock_waits", (char *)&export_vars.innodb_row_lock_waits, SHOW_LONG,
1479 SHOW_SCOPE_GLOBAL},
1480 {"rows_deleted", (char *)&export_vars.innodb_rows_deleted, SHOW_LONG,
1481 SHOW_SCOPE_GLOBAL},
1482 {"rows_inserted", (char *)&export_vars.innodb_rows_inserted, SHOW_LONG,
1483 SHOW_SCOPE_GLOBAL},
1484 {"rows_read", (char *)&export_vars.innodb_rows_read, SHOW_LONG,
1485 SHOW_SCOPE_GLOBAL},
1486 {"rows_updated", (char *)&export_vars.innodb_rows_updated, SHOW_LONG,
1487 SHOW_SCOPE_GLOBAL},
1488 {"system_rows_deleted", (char *)&export_vars.innodb_system_rows_deleted,
1489 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1490 {"system_rows_inserted", (char *)&export_vars.innodb_system_rows_inserted,
1491 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1492 {"system_rows_read", (char *)&export_vars.innodb_system_rows_read,
1493 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1494 {"system_rows_updated", (char *)&export_vars.innodb_system_rows_updated,
1495 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1496 {"sampled_pages_read", (char *)&export_vars.innodb_sampled_pages_read,
1497 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1498 {"sampled_pages_skipped", (char *)&export_vars.innodb_sampled_pages_skipped,
1499 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1500 {"num_open_files", (char *)&export_vars.innodb_num_open_files, SHOW_LONG,
1501 SHOW_SCOPE_GLOBAL},
1502 {"truncated_status_writes",
1503 (char *)&export_vars.innodb_truncated_status_writes, SHOW_LONG,
1504 SHOW_SCOPE_GLOBAL},
1505 {"undo_tablespaces_total",
1506 (char *)&export_vars.innodb_undo_tablespaces_total, SHOW_LONG,
1507 SHOW_SCOPE_GLOBAL},
1508 {"undo_tablespaces_implicit",
1509 (char *)&export_vars.innodb_undo_tablespaces_implicit, SHOW_LONG,
1510 SHOW_SCOPE_GLOBAL},
1511 {"undo_tablespaces_explicit",
1512 (char *)&export_vars.innodb_undo_tablespaces_explicit, SHOW_LONG,
1513 SHOW_SCOPE_GLOBAL},
1514 {"undo_tablespaces_active",
1515 (char *)&export_vars.innodb_undo_tablespaces_active, SHOW_LONG,
1516 SHOW_SCOPE_GLOBAL},
1517 #ifdef UNIV_DEBUG
1518 {"purge_trx_id_age", (char *)&export_vars.innodb_purge_trx_id_age,
1519 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1520 {"purge_view_trx_id_age", (char *)&export_vars.innodb_purge_view_trx_id_age,
1521 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1522 {"ahi_drop_lookups", (char *)&export_vars.innodb_ahi_drop_lookups,
1523 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1524 #endif /* UNIV_DEBUG */
1525 {"secondary_index_triggered_cluster_reads",
1526 (char *)&export_vars.innodb_sec_rec_cluster_reads, SHOW_LONG,
1527 SHOW_SCOPE_GLOBAL},
1528 {"secondary_index_triggered_cluster_reads_avoided",
1529 (char *)&export_vars.innodb_sec_rec_cluster_reads_avoided, SHOW_LONG,
1530 SHOW_SCOPE_GLOBAL},
1531 {"buffered_aio_submitted",
1532 (char *)&export_vars.innodb_buffered_aio_submitted, SHOW_LONG,
1533 SHOW_SCOPE_GLOBAL},
1534
1535 {"scan_pages_contiguous",
1536 (char *)&export_vars.innodb_fragmentation_stats.scan_pages_contiguous,
1537 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1538 {"scan_pages_disjointed",
1539 (char *)&export_vars.innodb_fragmentation_stats.scan_pages_disjointed,
1540 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1541 {"scan_pages_total_seek_distance",
1542 (char *)&export_vars.innodb_fragmentation_stats
1543 .scan_pages_total_seek_distance,
1544 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1545 {"scan_data_size",
1546 (char *)&export_vars.innodb_fragmentation_stats.scan_data_size, SHOW_LONG,
1547 SHOW_SCOPE_GLOBAL},
1548 {"scan_deleted_recs_size",
1549 (char *)&export_vars.innodb_fragmentation_stats.scan_deleted_recs_size,
1550 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1551 {"encryption_n_merge_blocks_encrypted",
1552 (char *)&export_vars.innodb_n_merge_blocks_encrypted, SHOW_LONGLONG,
1553 SHOW_SCOPE_GLOBAL},
1554 {"encryption_n_merge_blocks_decrypted",
1555 (char *)&export_vars.innodb_n_merge_blocks_decrypted, SHOW_LONGLONG,
1556 SHOW_SCOPE_GLOBAL},
1557 {"encryption_n_rowlog_blocks_encrypted",
1558 (char *)&export_vars.innodb_n_rowlog_blocks_encrypted, SHOW_LONGLONG,
1559 SHOW_SCOPE_GLOBAL},
1560 {"encryption_n_rowlog_blocks_decrypted",
1561 (char *)&export_vars.innodb_n_rowlog_blocks_decrypted, SHOW_LONGLONG,
1562 SHOW_SCOPE_GLOBAL},
1563 {"encryption_redo_key_version",
1564 (char *)&export_vars.innodb_redo_key_version, SHOW_LONGLONG,
1565 SHOW_SCOPE_GLOBAL},
1566 {NullS, NullS, SHOW_LONG, SHOW_SCOPE_GLOBAL},
1567 /* Encryption */
1568 {"encryption_rotation_pages_read_from_cache",
1569 (char *)&export_vars.innodb_encryption_rotation_pages_read_from_cache,
1570 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1571 {"encryption_rotation_pages_read_from_disk",
1572 (char *)&export_vars.innodb_encryption_rotation_pages_read_from_disk,
1573 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1574 {"encryption_rotation_pages_modified",
1575 (char *)&export_vars.innodb_encryption_rotation_pages_modified, SHOW_LONG,
1576 SHOW_SCOPE_GLOBAL},
1577 {"encryption_rotation_pages_flushed",
1578 (char *)&export_vars.innodb_encryption_rotation_pages_flushed, SHOW_LONG,
1579 SHOW_SCOPE_GLOBAL},
1580 {"encryption_rotation_estimated_iops",
1581 (char *)&export_vars.innodb_encryption_rotation_estimated_iops, SHOW_LONG,
1582 SHOW_SCOPE_GLOBAL},
1583 {"encryption_key_rotation_list_length",
1584 (char *)&export_vars.innodb_key_rotation_list_length, SHOW_LONGLONG,
1585 SHOW_SCOPE_GLOBAL},
1586 {"num_pages_encrypted", (char *)&export_vars.innodb_pages_encrypted,
1587 SHOW_LONGLONG, SHOW_SCOPE_GLOBAL},
1588 {"num_pages_decrypted", (char *)&export_vars.innodb_pages_decrypted,
1589 SHOW_LONGLONG, SHOW_SCOPE_GLOBAL},
1590 {NullS, NullS, SHOW_LONG, SHOW_SCOPE_GLOBAL}};
1591
1592 /** Handling the shared INNOBASE_SHARE structure that is needed to provide table
1593 locking. Register the table name if it doesn't exist in the hash table. */
1594 static INNOBASE_SHARE *get_share(
1595 const char *table_name); /*!< in: table to lookup */
1596
1597 /** Free the shared object that was registered with get_share(). */
1598 static void free_share(INNOBASE_SHARE *share); /*!< in/own: share to free */
1599
1600 /** Calls free_share and assign nullptr to share.
1601 @param[in,out] share table share to free */
1602 3917077 static void free_share_and_nullify(
1603 INNOBASE_SHARE **share) /*!< in/own: table share to free */
1604 {
1605 3917077 free_share(*share);
1606 3917082 *share = nullptr;
1607 3917082 }
1608
1609 /** Frees a possible InnoDB trx object associated with the current THD.
1610 @return 0 or error number */
1611 static int innobase_close_connection(
1612 handlerton *hton, /*!< in/out: InnoDB handlerton */
1613 THD *thd); /*!< in: MySQL thread handle for
1614 which to close the connection */
1615
1616 /** Cancel any pending lock request associated with the current THD. */
1617 static void innobase_kill_connection(
1618 handlerton *hton, /*!< in/out: InnoDB handlerton */
1619 THD *thd); /*!< in: MySQL thread handle for
1620 which to close the connection */
1621
1622 /** Commits a transaction in an InnoDB database or marks an SQL statement
1623 ended.
1624 @return 0 */
1625 static int innobase_commit(handlerton *hton, /*!< in/out: InnoDB handlerton */
1626 THD *thd, /*!< in: MySQL thread handle of the
1627 user for whom the transaction should
1628 be committed */
1629 bool commit_trx); /*!< in: true - commit transaction
1630 false - the current SQL statement
1631 ended */
1632
1633 /** Rolls back a transaction to a savepoint.
1634 @return 0 if success, HA_ERR_NO_SAVEPOINT if no savepoint with the
1635 given name */
1636 static int innobase_rollback(handlerton *hton, /*!< in/out: InnoDB handlerton */
1637 THD *thd, /*!< in: handle to the MySQL thread
1638 of the user whose transaction should
1639 be rolled back */
1640 bool rollback_trx); /*!< in: true - rollback entire
1641 transaction false - rollback
1642 the current statement only */
1643
1644 /** Rolls back a transaction to a savepoint.
1645 @return 0 if success, HA_ERR_NO_SAVEPOINT if no savepoint with the
1646 given name */
1647 static int innobase_rollback_to_savepoint(
1648 handlerton *hton, /*!< in/out: InnoDB handlerton */
1649 THD *thd, /*!< in: handle to the MySQL thread of
1650 the user whose XA transaction should
1651 be rolled back to savepoint */
1652 void *savepoint); /*!< in: savepoint data */
1653
1654 /** Check whether innodb state allows to safely release MDL locks after
1655 rollback to savepoint.
1656 @return true if it is safe, false if its not safe. */
1657 static bool innobase_rollback_to_savepoint_can_release_mdl(
1658 handlerton *hton, /*!< in/out: InnoDB handlerton */
1659 THD *thd); /*!< in: handle to the MySQL thread of
1660 the user whose XA transaction should
1661 be rolled back to savepoint */
1662
1663 /** Sets a transaction savepoint.
1664 @return always 0, that is, always succeeds */
1665 static int innobase_savepoint(
1666 handlerton *hton, /*!< in/out: InnoDB handlerton */
1667 THD *thd, /*!< in: handle to the MySQL thread of
1668 the user's XA transaction for which
1669 we need to take a savepoint */
1670 void *savepoint); /*!< in: savepoint data */
1671
1672 /** Release transaction savepoint name.
1673 @return 0 if success, HA_ERR_NO_SAVEPOINT if no savepoint with the
1674 given name */
1675 static int innobase_release_savepoint(
1676 handlerton *hton, /*!< in/out: handlerton for InnoDB */
1677 THD *thd, /*!< in: handle to the MySQL thread
1678 of the user whose transaction's
1679 savepoint should be released */
1680 void *savepoint); /*!< in: savepoint data */
1681
1682 /** Function for constructing an InnoDB table handler instance.
1683 @param[in,out] hton handlerton for InnoDB
1684 @param[in] table MySQL table
1685 @param[in] partitioned Indicates whether table is partitioned
1686 @param[in] mem_root memory context */
1687 static handler *innobase_create_handler(handlerton *hton, TABLE_SHARE *table,
1688 bool partitioned, MEM_ROOT *mem_root);
1689
1690 /** Retrieve table satistics.
1691 @param[in] db_name database name
1692 @param[in] table_name table name
1693 @param[in] se_private_id The internal id of the table
1694 @param[in] ts_se_private_data Tablespace SE Private data
1695 @param[in] tbl_se_private_data Table SE private data
1696 @param[in] stat_flags flags used to retrieve specific stats
1697 @param[in,out] stats structure to save the
1698 retrieved statistics
1699 @return false on success, true on failure */
1700 static bool innobase_get_table_statistics(
1701 const char *db_name, const char *table_name, dd::Object_id se_private_id,
1702 const dd::Properties &ts_se_private_data,
1703 const dd::Properties &tbl_se_private_data, uint stat_flags,
1704 ha_statistics *stats);
1705
1706 /** Retrieve index column cardinality.
1707 @param[in] db_name name of schema
1708 @param[in] table_name name of table
1709 @param[in] index_name name of index
1710 @param[in] index_ordinal_position position of index
1711 @param[in] column_ordinal_position position of column in index
1712 @param[in] se_private_id the internal id of the table
1713 @param[in,out] cardinality cardinality of index column
1714 @retval false success
1715 @retval true failure */
1716 static bool innobase_get_index_column_cardinality(
1717 const char *db_name, const char *table_name, const char *index_name,
1718 uint index_ordinal_position, uint column_ordinal_position,
1719 dd::Object_id se_private_id, ulonglong *cardinality);
1720
1721 /** Retrieve ha_tablespace_statistics for the tablespace.
1722
1723 @param tablespace_name Tablespace_name
1724 @param file_name Data file name.
1725 @param ts_se_private_data Tablespace SE private data.
1726 @param[out] stats Contains tablespace
1727 statistics read from SE.
1728 @return false on success, true on failure */
1729 static bool innobase_get_tablespace_statistics(
1730 const char *tablespace_name, const char *file_name,
1731 const dd::Properties &ts_se_private_data, ha_tablespace_statistics *stats);
1732
1733 static bool innobase_is_tablespace_keyring_pre_v3_encrypted(
1734 const dd::Tablespace &tablespace, int &error);
1735 /** Retrieve the tablespace type.
1736
1737 @param space Tablespace object.
1738 @param[out] space_type Tablespace category.
1739 @return false on success, true on failure */
1740 static bool innobase_get_tablespace_type(const dd::Tablespace &space,
1741 Tablespace_type *space_type);
1742
1743 /** Get the tablespace type given the name.
1744
1745 @param[in] tablespace_name tablespace name
1746 @param[out] space_type type of space
1747
1748 @return Operation status.
1749 @retval false on success and true for failure.
1750 */
1751 static bool innobase_get_tablespace_type_by_name(const char *tablespace_name,
1752 Tablespace_type *space_type);
1753
1754 /** Perform post-commit/rollback cleanup after DDL statement.
1755 @param[in,out] thd connection thread */
1756 static void innobase_post_ddl(THD *thd);
1757
1758 /** Check if types of child and parent columns in foreign key are compatible.
1759 @param[in] child_column_type Child column type description.
1760 @param[in] parent_column_type Parent column type description.
1761 @param[in] check_charsets Indicates whether we need to check
1762 that charsets of string columns
1763 match. Which is true in most cases.
1764 @return True if types are compatible, False if not. */
1765 static bool innodb_check_fk_column_compat(
1766 const Ha_fk_column_type *child_column_type,
1767 const Ha_fk_column_type *parent_column_type, bool check_charsets);
1768
1769 /** @brief Initialize the default value of innodb_commit_concurrency.
1770
1771 Once InnoDB is running, the innodb_commit_concurrency must not change
1772 from zero to nonzero. (Bug #42101)
1773
1774 The initial default value is 0, and without this extra initialization,
1775 SET GLOBAL innodb_commit_concurrency=DEFAULT would set the parameter
1776 to 0, even if it was initially set to nonzero at the command line
1777 or configuration file. */
1778 static void innobase_commit_concurrency_init_default();
1779
1780 /** This function is used to prepare an X/Open XA distributed transaction.
1781 @return 0 or error number */
1782 static int innobase_xa_prepare(handlerton *hton, /*!< in: InnoDB handlerton */
1783 THD *thd, /*!< in: handle to the MySQL thread of
1784 the user whose XA transaction should
1785 be prepared */
1786 bool all); /*!< in: true - prepare transaction
1787 false - the current SQL statement
1788 ended */
1789 /** This function is used to recover X/Open XA distributed transactions.
1790 @return number of prepared transactions stored in xid_list */
1791 static int innobase_xa_recover(
1792 handlerton *hton, /*!< in: InnoDB handlerton */
1793 XA_recover_txn *txn_list, /*!< in/out: prepared transactions */
1794 uint len, /*!< in: number of slots in xid_list */
1795 MEM_ROOT *mem_root); /*!< in: memory for table names */
1796 /** Find prepared transactions that are marked as prepared in TC, for recovery
1797 purposes.
1798 @param[in] hton InnoDB handlerton
1799 @param[in,out] xa_list prepared transactions state
1800 @return 0 if successful or error number */
1801 static int innobase_xa_recover_prepared_in_tc(handlerton *hton,
1802 Xa_state_list &xa_list);
1803 /** This function is used to commit one X/Open XA distributed transaction
1804 which is in the prepared state
1805 @return 0 or error number */
1806 static xa_status_code innobase_commit_by_xid(
1807 handlerton *hton, /*!< in: InnoDB handlerton */
1808 XID *xid); /*!< in: X/Open XA transaction
1809 identification */
1810 /** This function is used to rollback one X/Open XA distributed transaction
1811 which is in the prepared state
1812 @return 0 or error number */
1813 static xa_status_code innobase_rollback_by_xid(
1814 handlerton *hton, /*!< in: InnoDB handlerton */
1815 XID *xid); /*!< in: X/Open XA transaction
1816 identification */
1817 /** This function is used to write mark an X/Open XA distributed transaction
1818 as been prepared in the server transaction coordinator
1819 @param[in] hton InnoDB handlerton
1820 @param[in] thd handle to the MySQL thread of the user whose XA transaction
1821 should be prepared
1822 @return 0 or error number */
1823 static int innobase_set_prepared_in_tc(handlerton *hton, THD *thd);
1824 /** Mark an X/Open XA distributed transaction
1825 as been prepared in the server transaction coordinator
1826 @param[in] hton InnoDB handlerton
1827 @param[in] xid X/Open XA transaction identification the MySQL thread of the
1828 user whosefo the XA transaction that should be prepared
1829 @return XA_OK or error number */
1830 static xa_status_code innobase_set_prepared_in_tc_by_xid(handlerton *hton,
1831 XID *xid);
1832 /** Checks if the file name is reserved in InnoDB. Currently
1833 redo log file names from the old redo format (ib_logfile*)
1834 are reserved. There is no need to reserve file names from the
1835 newer redo formats, because they start with '#'.
1836 @return true if the name is reserved
1837 @param[in] hton handlerton of InnoDB
1838 @param[in] name Name of the database */
1839 static bool innobase_check_reserved_file_name(handlerton *hton,
1840 const char *name);
1841 /** Check tablespace name validity.
1842 @param[in] ts_cmd whether this is tablespace DDL or not
1843 @param[in] name name to check
1844 @retval false invalid name
1845 @retval true valid name */
1846 static bool innobase_is_valid_tablespace_name(ts_command_type ts_cmd,
1847 const char *name);
1848
1849 /** This API handles CREATE, ALTER & DROP commands for InnoDB tablespaces.
1850 @param[in] hton Handlerton of InnoDB
1851 @param[in] thd Connection
1852 @param[in] alter_info Describes the command and how to do it.
1853 @param[in] old_ts_def Old version of dd::Tablespace object for the
1854 tablespace.
1855 @param[in,out] new_ts_def New version of dd::Tablespace object for the
1856 tablespace. Can be adjusted by SE. Changes will be persisted in the
1857 data-dictionary at statement commit.
1858 @return MySQL error code*/
1859 static int innobase_alter_tablespace(handlerton *hton, THD *thd,
1860 st_alter_tablespace *alter_info,
1861 const dd::Tablespace *old_ts_def,
1862 dd::Tablespace *new_ts_def);
1863
1864 /**
1865 Get tablespace datafile name extension.
1866 */
1867 static const char *innobase_get_tablespace_filename_ext();
1868
1869 /** Free tablespace resources. */
1870 8368 static void innodb_space_shutdown() {
1871
1/2
✓ Branch 0 taken 8368 times.
✗ Branch 1 not taken.
8368 DBUG_TRACE;
1872
1873
1/2
✓ Branch 0 taken 8368 times.
✗ Branch 1 not taken.
8368 srv_sys_space.shutdown();
1874
2/2
✓ Branch 0 taken 8270 times.
✓ Branch 1 taken 98 times.
8368 if (srv_tmp_space.get_sanity_check_status()) {
1875
1/2
✓ Branch 0 taken 8270 times.
✗ Branch 1 not taken.
8270 fil_space_close(srv_tmp_space.space_id());
1876
1/2
✓ Branch 0 taken 8270 times.
✗ Branch 1 not taken.
8270 srv_tmp_space.delete_files();
1877 }
1878
1/2
✓ Branch 0 taken 8368 times.
✗ Branch 1 not taken.
8368 srv_tmp_space.shutdown();
1879 8368 }
1880
1881 /** Shut down InnoDB after the Global Data Dictionary has been shut down.
1882 @see innodb_pre_dd_shutdown()
1883 @retval 0 always */
1884 8361 static int innodb_shutdown(handlerton *, ha_panic_function) {
1885
1/2
✓ Branch 0 taken 8361 times.
✗ Branch 1 not taken.
8361 DBUG_TRACE;
1886
1887
2/2
✓ Branch 0 taken 8267 times.
✓ Branch 1 taken 94 times.
8361 if (innodb_inited) {
1888
1/2
✓ Branch 0 taken 8267 times.
✗ Branch 1 not taken.
8267 log_pfs_delete_tables();
1889
1890 8267 innodb_inited = false;
1891 8267 ut::delete_(innobase_open_tables);
1892 8267 innobase_open_tables = nullptr;
1893
1894
2/2
✓ Branch 0 taken 8295 times.
✓ Branch 1 taken 8267 times.
16562 for (auto file : innobase_sys_files) {
1895 8295 ut::delete_(file);
1896 }
1897 8267 innobase_sys_files.clear();
1898
1/2
✓ Branch 0 taken 8267 times.
✗ Branch 1 not taken.
8267 innobase_sys_files.shrink_to_fit();
1899
1900
1/2
✓ Branch 0 taken 8267 times.
✗ Branch 1 not taken.
8267 mutex_free(&master_key_id_mutex);
1901
1/2
✓ Branch 0 taken 8267 times.
✗ Branch 1 not taken.
8267 srv_shutdown();
1902
1/2
✓ Branch 0 taken 8267 times.
✗ Branch 1 not taken.
8267 innodb_space_shutdown();
1903
1904
1/2
✓ Branch 0 taken 8267 times.
✗ Branch 1 not taken.
8267 mysql_mutex_destroy(&innobase_share_mutex);
1905
1/2
✓ Branch 0 taken 8267 times.
✗ Branch 1 not taken.
8267 mysql_mutex_destroy(&commit_cond_m);
1906
1/2
✓ Branch 0 taken 8267 times.
✗ Branch 1 not taken.
8267 mysql_cond_destroy(&commit_cond);
1907
1/2
✓ Branch 0 taken 8267 times.
✗ Branch 1 not taken.
8267 mysql_mutex_destroy(&resume_encryption_cond_m);
1908
1/2
✓ Branch 0 taken 8267 times.
✗ Branch 1 not taken.
8267 mysql_cond_destroy(&resume_encryption_cond);
1909 }
1910
1911
1/2
✓ Branch 0 taken 8361 times.
✗ Branch 1 not taken.
8361 os_event_global_destroy();
1912
1913
1/2
✓ Branch 0 taken 8361 times.
✗ Branch 1 not taken.
8361 innobase::component_services::deinitialize_service_handles();
1914
1915 8361 return 0;
1916 8361 }
1917
1918 /** Shut down all InnoDB background tasks that may access
1919 the Global Data Dictionary, before the Global Data Dictionary
1920 and the rest of InnoDB have been shut down.
1921 @see dd::shutdown()
1922 @see innodb_shutdown() */
1923 8374 static void innodb_pre_dd_shutdown(handlerton *) {
1924
2/2
✓ Branch 0 taken 8280 times.
✓ Branch 1 taken 94 times.
8374 if (innodb_inited) {
1925 8280 srv_pre_dd_shutdown();
1926 }
1927 8361 }
1928
1929 /** Stores the current binlog coordinates in the trx system header.
1930 @param[in] hton InnoDB handlerton
1931 @param[in] thd MySQL thrad handle */
1932 static int innobase_store_binlog_info(handlerton *hton, THD *thd) noexcept;
1933
1934 /** Creates an InnoDB transaction struct for the thd if it does not yet have
1935 one. Starts a new InnoDB transaction if a transaction is not yet started. And
1936 assigns a new snapshot for a consistent read if the transaction does not yet
1937 have one.
1938 @return 0 */
1939 static int innobase_start_trx_and_assign_read_view(
1940 handlerton *hton, /* in: InnoDB handlerton */
1941 THD *thd); /* in: MySQL thread handle of the
1942 user for whom the transaction should
1943 be committed */
1944
1945 /** Creates an InnoDB transaction struct for the thd if it does not
1946 yet have one. Starts a new InnoDB transaction if a transaction is not
1947 yet started. And clones snapshot for a consistent read from another
1948 session, if it has one.
1949 @param[in] hton InnoDB handlerton
1950 @param[in] thd MySQL thread handle of the user for whom the
1951 transaction should be committed
1952 @param[in] from_thd MySQL thread handle of the user session from
1953 which the consistent read should be cloned
1954 @return 0 */
1955 static int innobase_start_trx_and_clone_read_view(handlerton *hton, THD *thd,
1956 THD *from_thd);
1957
1958 /** Flush InnoDB redo logs to the file system.
1959 @param[in] hton InnoDB handlerton
1960 @param[in] binlog_group_flush true if we got invoked by binlog
1961 group commit during flush stage, false in other cases.
1962 @return false */
1963 static bool innobase_flush_logs(handlerton *hton, bool binlog_group_flush);
1964
1965 /** Implements the SHOW ENGINE INNODB STATUS command. Sends the output of the
1966 InnoDB Monitor to the client.
1967 @param[in] hton the innodb handlerton
1968 @param[in] thd the MySQL query thread of the caller
1969 @param[in] stat_print print function
1970 @return 0 on success */
1971 static int innodb_show_status(handlerton *hton, THD *thd,
1972 stat_print_fn *stat_print);
1973
1974 /** Implements Log_resource lock.
1975 @param[in] hton the innodb handlerton
1976 @return false on success */
1977 static bool innobase_lock_hton_log(handlerton *hton);
1978
1979 /** Implements Log_resource unlock.
1980 @param[in] hton the innodb handlerton
1981 @return false on success */
1982 static bool innobase_unlock_hton_log(handlerton *hton);
1983
1984 /** Implements Log_resource collect_info.
1985 @param[in] hton the innodb handlerton
1986 @param[in] json the JSON dom to receive the log info
1987 @return false on success */
1988 static bool innobase_collect_hton_log_info(handlerton *hton, Json_dom *json);
1989
1990 /** Return 0 on success and non-zero on failure. Note: the bool return type
1991 seems to be abused here, should be an int.
1992 @param[in] hton the innodb handlerton
1993 @param[in] thd the MySQL query thread of the caller
1994 @param[in] stat_print print function
1995 @param[in] stat_type status to show */
1996 static bool innobase_show_status(handlerton *hton, THD *thd,
1997 stat_print_fn *stat_print,
1998 enum ha_stat_type stat_type);
1999
2000 /** Parse and enable InnoDB monitor counters during server startup.
2001 User can enable monitor counters/groups by specifying
2002 "loose-innodb_monitor_enable = monitor_name1;monitor_name2..."
2003 in server configuration file or at the command line. */
2004 static void innodb_enable_monitor_at_startup(
2005 char *str); /*!< in: monitor counter enable list */
2006
2007 /** Fill handlerton based INFORMATION_SCHEMA tables.
2008 @param[in] hton (unused) Handle to the handlerton structure
2009 @param[in] thd Thread/connection descriptor
2010 @param[in,out] tables Information Schema tables to fill
2011 @param[in] idx_cond (unused) Intended for conditional pushdown
2012 @param[in] idx Table id that indicates which I_S table to fill
2013 @return Operation status */
2014 4 static int innobase_fill_i_s_table(handlerton *hton [[maybe_unused]],
2015 THD *thd [[maybe_unused]],
2016 TABLE_LIST *tables [[maybe_unused]],
2017 Item *idx_cond [[maybe_unused]],
2018 enum_schema_tables idx) {
2019
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 assert(idx == SCH_TABLESPACES);
2020
2021 /** InnoDB does not implement I_S.TABLESPACES */
2022
2023 4 return (0);
2024 }
2025
2026 /** Store doc_id value into FTS_DOC_ID field
2027 @param[in,out] tbl table containing FULLTEXT index
2028 @param[in] doc_id FTS_DOC_ID value */
2029 134 static void innobase_fts_store_docid(TABLE *tbl, ulonglong doc_id) {
2030 134 my_bitmap_map *old_map = dbug_tmp_use_all_columns(tbl, tbl->write_set);
2031
2032 134 tbl->fts_doc_id_field->store(static_cast<longlong>(doc_id), true);
2033
2034 134 dbug_tmp_restore_column_map(tbl->write_set, old_map);
2035 134 }
2036
2037 /** Check for a valid value of innobase_commit_concurrency.
2038 @return 0 for valid innodb_commit_concurrency */
2039 17 static int innobase_commit_concurrency_validate(
2040 THD *, /*!< in: thread handle */
2041 SYS_VAR *, /*!< in: pointer to system
2042 variable */
2043 void *save, /*!< out: immediate result
2044 for update function */
2045 struct st_mysql_value *value) /*!< in: incoming string */
2046 {
2047 long long intbuf;
2048 ulong commit_concurrency;
2049
2050
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 DBUG_TRACE;
2051
2052
2/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
17 if (value->val_int(value, &intbuf)) {
2053 /* The value is NULL. That is invalid. */
2054 return 1;
2055 }
2056
2057 17 *reinterpret_cast<ulong *>(save) = commit_concurrency =
2058 17 static_cast<ulong>(intbuf);
2059
2060 /* Allow the value to be updated, as long as it remains zero
2061 or nonzero. */
2062 17 return !(!commit_concurrency == !innobase_commit_concurrency);
2063 17 }
2064
2065 /** Function for constructing an InnoDB table handler instance.
2066 @param[in,out] hton handlerton for InnoDB
2067 @param[in] table MySQL table
2068 @param[in] partitioned Indicates whether table is partitioned
2069 @param[in] mem_root memory context */
2070 9236908 static handler *innobase_create_handler(handlerton *hton, TABLE_SHARE *table,
2071 bool partitioned, MEM_ROOT *mem_root) {
2072
2/2
✓ Branch 0 taken 103880 times.
✓ Branch 1 taken 9133028 times.
9236908 if (partitioned) {
2073
2/4
✓ Branch 0 taken 103881 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 103881 times.
✗ Branch 3 not taken.
103880 ha_innopart *file = new (mem_root) ha_innopart(hton, table);
2074
3/6
✓ Branch 0 taken 103881 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 103881 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 103881 times.
103881 if (file && file->init_partitioning(mem_root)) {
2075 destroy(file);
2076 return (nullptr);
2077 }
2078 103881 return (file);
2079 }
2080
2081
2/4
✓ Branch 0 taken 9133048 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9133047 times.
✗ Branch 3 not taken.
9133028 return (new (mem_root) ha_innobase(hton, table));
2082 }
2083
2084 /* General functions */
2085
2086 /** Returns true if the thread is the replication thread on the slave
2087 server. Used in srv_conc_enter_innodb() to determine if the thread
2088 should be allowed to enter InnoDB - the replication thread is treated
2089 differently than other threads. Also used in
2090 srv_conc_force_exit_innodb().
2091 @return true if thd is the replication thread */
2092 157387 bool thd_is_replication_slave_thread(THD *thd) /*!< in: thread handle */
2093 {
2094
3/4
✓ Branch 0 taken 157387 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 540 times.
✓ Branch 3 taken 156847 times.
157387 return thd != nullptr && thd_slave_thread(thd);
2095 }
2096
2097 /** Gets information on the durability property requested by thread.
2098 Used when writing either a prepare or commit record to the log
2099 buffer. @return the durability property. */
2100 7105125 enum durability_properties thd_requested_durability(
2101 const THD *thd) /*!< in: thread handle */
2102 {
2103 7105125 return (thd_get_durability_property(thd));
2104 }
2105
2106 /** Returns true if transaction should be flagged as read-only.
2107 @return true if the thd is marked as read-only */
2108 17400167 bool thd_trx_is_read_only(THD *thd) /*!< in: thread handle */
2109 {
2110
4/4
✓ Branch 0 taken 17229889 times.
✓ Branch 1 taken 170278 times.
✓ Branch 2 taken 11942231 times.
✓ Branch 3 taken 5287647 times.
17400167 return (thd != nullptr && thd_tx_is_read_only(thd));
2111 }
2112
2113 /**
2114 Check if the transaction can be rolled back
2115 @param[in] requestor Session requesting the lock
2116 @param[in] holder Session that holds the lock
2117 @return the session that will be rolled back, null don't care */
2118
2119 THD *thd_trx_arbitrate(THD *requestor, THD *holder) {
2120 /* Non-user (thd==0) transactions by default can't rollback, in
2121 practice DDL transactions should never rollback and that's because
2122 they should never wait on table/record locks either */
2123
2124 ut_a(holder != nullptr);
2125 ut_a(holder != requestor);
2126
2127 THD *victim = thd_tx_arbitrate(requestor, holder);
2128
2129 ut_a(victim == nullptr || victim == requestor || victim == holder);
2130
2131 return (victim);
2132 }
2133
2134 /**
2135 @param[in] thd Session to check
2136 @return the priority */
2137
2138 394364547 int thd_trx_priority(THD *thd) {
2139
1/2
✓ Branch 0 taken 394364745 times.
✗ Branch 1 not taken.
394364547 return (thd == nullptr ? 0 : thd_tx_priority(thd));
2140 }
2141
2142 /** Check if the transaction is an auto-commit transaction. true also
2143 implies that it is a SELECT (read-only) transaction.
2144 @return true if the transaction is an auto commit read-only transaction. */
2145 19653737 bool thd_trx_is_auto_commit(THD *thd) /*!< in: thread handle, can be NULL */
2146 {
2147 17230267 return thd != nullptr &&
2148
4/4
✓ Branch 0 taken 17230379 times.
✓ Branch 1 taken 2423358 times.
✓ Branch 2 taken 16071904 times.
✓ Branch 3 taken 1158363 times.
35725632 !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) &&
2149
2/2
✓ Branch 0 taken 12609459 times.
✓ Branch 1 taken 3462436 times.
35725520 thd_is_query_block(thd);
2150 }
2151
2152 extern "C" long long thd_start_time(const THD *thd);
2153
2154 17228998 std::chrono::system_clock::time_point thd_start_time(THD *) {
2155 // FIXME: This function should be added to the server code.
2156 // return(thd_start_time(thd));
2157 17228998 return std::chrono::system_clock::now();
2158 }
2159
2160 /** Enter InnoDB engine after checking the max number of user threads
2161 allowed, else the thread is put into sleep.
2162 @param[in,out] prebuilt row prebuilt handler
2163 @return InnoDB error code. */
2164 537989476 static inline dberr_t innobase_srv_conc_enter_innodb(row_prebuilt_t *prebuilt) {
2165 /* We rely on server to do external_lock(F_UNLCK) to reset the
2166 srv_conc.n_active counter. */
2167
2/2
✓ Branch 0 taken 226135962 times.
✓ Branch 1 taken 311855151 times.
537989476 if (prebuilt->skip_concurrency_ticket()) {
2168 226135962 return DB_SUCCESS;
2169 }
2170
2171 #ifdef WITH_WSREP
2172 // innodb_thread_concurreny limit how many thread can work in innodb
2173 // at any given time. This limit is not applicable to wsrep-applier
2174 // threads given they are high priority threads.
2175
4/4
✓ Branch 0 taken 26139490 times.
✓ Branch 1 taken 285715306 times.
✓ Branch 2 taken 3470521 times.
✓ Branch 3 taken 308384350 times.
337994716 if (wsrep_on(prebuilt->trx->mysql_thd) &&
2176
2/2
✓ Branch 0 taken 3470522 times.
✓ Branch 1 taken 22669043 times.
26139490 wsrep_thd_is_BF(prebuilt->trx->mysql_thd, false))
2177 3470521 return DB_SUCCESS;
2178 #endif /* WITH_WSREP */
2179
2180 308384350 dberr_t err = DB_SUCCESS;
2181 308384350 trx_t *trx = prebuilt->trx;
2182
2183
2/2
✓ Branch 0 taken 41353 times.
✓ Branch 1 taken 308342997 times.
308384350 if (srv_thread_concurrency) {
2184
2/2
✓ Branch 0 taken 39426 times.
✓ Branch 1 taken 1927 times.
41353 if (trx->n_tickets_to_enter_innodb > 0) {
2185 /* If trx has 'free tickets' to enter the engine left,
2186 then use one such ticket */
2187
2188 39426 --trx->n_tickets_to_enter_innodb;
2189
2190
2/4
✓ Branch 0 taken 1928 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1927 times.
3855 } else if (trx->mysql_thd != nullptr &&
2191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1928 times.
1928 thd_is_replication_slave_thread(trx->mysql_thd)) {
2192 ut::wait_for(
2193 [&]() {
2194 return srv_conc_get_active_threads() <
2195 (int32_t)srv_thread_concurrency;
2196 },
2197 get_srv_replication_delay());
2198
2199 } else {
2200 1927 err = srv_conc_enter_innodb(prebuilt);
2201 }
2202 }
2203
2204 308384351 return err;
2205 }
2206
2207 /** Note that the thread wants to leave InnoDB only if it doesn't have
2208 any spare tickets.
2209 @param[in,out] prebuilt row prebuilt handler */
2210 537990997 static inline void innobase_srv_conc_exit_innodb(row_prebuilt_t *prebuilt) {
2211 #ifdef WITH_WSREP
2212 // innodb_thread_concurreny limit how many thread can work in innodb
2213 // at any given time. This limit is not applicable to wsrep-applier
2214 // threads given they are high priority threads.
2215
5/6
✓ Branch 0 taken 537991922 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32264663 times.
✓ Branch 3 taken 505727259 times.
✓ Branch 4 taken 4983676 times.
✓ Branch 5 taken 533008246 times.
570255660 if (wsrep_on(prebuilt->trx->mysql_thd) &&
2216
3/4
✓ Branch 0 taken 32264663 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4983676 times.
✓ Branch 3 taken 27280987 times.
32264663 wsrep_thd_is_BF(prebuilt->trx->mysql_thd, false))
2217 229606616 return;
2218 #endif /* WITH_WSREP */
2219
2220 /* We rely on server to do external_lock(F_UNLCK) to reset the
2221 srv_conc.n_active counter. */
2222
3/4
✓ Branch 0 taken 533008341 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 224622940 times.
✓ Branch 3 taken 308385401 times.
533008246 if (prebuilt->skip_concurrency_ticket()) {
2223 224622940 return;
2224 }
2225
2226 308385401 trx_t *trx = prebuilt->trx;
2227 #ifdef UNIV_DEBUG
2228 308385401 btrsea_sync_check check(trx->has_search_latch);
2229
2230
2/4
✓ Branch 0 taken 308385513 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 308385426 times.
308385548 ut_ad(!sync_check_iterate(check));
2231 #endif /* UNIV_DEBUG */
2232
2233 /* This is to avoid making an unnecessary function call. */
2234
2/2
✓ Branch 0 taken 41352 times.
✓ Branch 1 taken 308344074 times.
308385426 if (trx->declared_to_be_inside_innodb &&
2235
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 41349 times.
41352 trx->n_tickets_to_enter_innodb == 0) {
2236
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 srv_conc_force_exit_innodb(trx);
2237 }
2238 308385426 }
2239
2240 /** Force a thread to leave InnoDB even if it has spare tickets. */
2241 156971059 static inline void innobase_srv_conc_force_exit_innodb(
2242 trx_t *trx) /*!< in: transaction handle */
2243 {
2244 #ifdef UNIV_DEBUG
2245 156971059 btrsea_sync_check check(trx->has_search_latch);
2246
2247
2/4
✓ Branch 0 taken 156971459 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 156971086 times.
156971285 ut_ad(!sync_check_iterate(check));
2248 #endif /* UNIV_DEBUG */
2249
2250 /* This is to avoid making an unnecessary function call. */
2251
2/2
✓ Branch 0 taken 1923 times.
✓ Branch 1 taken 156969163 times.
156971086 if (trx->declared_to_be_inside_innodb) {
2252
1/2
✓ Branch 0 taken 1924 times.
✗ Branch 1 not taken.
1923 srv_conc_force_exit_innodb(trx);
2253 }
2254 156971087 }
2255
2256 /** Returns the NUL terminated value of glob_hostname.
2257 @return pointer to glob_hostname. */
2258 644 const char *server_get_hostname() { return (glob_hostname); }
2259
2260 /** Returns true if the transaction this thread is processing has edited
2261 non-transactional tables. Used by the deadlock detector when deciding
2262 which transaction to rollback in case of a deadlock - we try to avoid
2263 rolling back transactions that have edited non-transactional tables.
2264 @return true if non-transactional tables have been edited */
2265 392 bool thd_has_edited_nontrans_tables(THD *thd) /*!< in: thread handle */
2266 {
2267 392 return thd_non_transactional_update(thd);
2268 }
2269
2270 /** Returns true if the thread is executing a SELECT statement.
2271 @return true if thd is executing SELECT */
2272 16687657 bool thd_is_query_block(const THD *thd) /*!< in: thread handle */
2273 {
2274 16687657 return thd_sql_command(thd) == SQLCOM_SELECT;
2275 }
2276
2277 /** Checks sys_vars and determines if allocator should mark
2278 large memory segments with MADV_DONTDUMP
2279 @return true iff @@global.core_file AND
2280 NOT @@global.innodb_buffer_pool_in_core_file */
2281 9693 bool innobase_should_madvise_buf_pool() {
2282
4/4
✓ Branch 0 taken 8967 times.
✓ Branch 1 taken 726 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 8963 times.
9693 return (test_flags & TEST_CORE_ON_SIGNAL) && !srv_buffer_pool_in_core_file;
2283 }
2284
2285 /** Make sure that core file will not be generated, as generating a core file
2286 might violate our promise to not dump buffer pool data, and/or might dump not
2287 the expected memory pages due to failure in using madvise */
2288 void innobase_disable_core_dump() {
2289 /* TODO: There is a race condition here, as test_flags is not an atomic<>
2290 and there might be multiple threads calling this function
2291 in parallel (once for each buffer pool thread).
2292 One approach would be to use a loop with os_compare_and_swap_ulint
2293 unfortunately test_flags is defined as uint, not ulint, and we don't
2294 have nice portable function for dealing with uint in InnoDB.
2295 Moreover that would only prevent problems with mangled bits, but not
2296 help at all with that some other thread might be reading test_flags
2297 and making decisions based on observed value while we are changing it.
2298 The good news is that all these threads try to do the same thing: clear the
2299 same bit. So this happens to work.
2300 */
2301
2302 test_flags &= ~TEST_CORE_ON_SIGNAL;
2303 }
2304
2305 208095 std::chrono::seconds thd_lock_wait_timeout(THD *thd) {
2306 /* According to <mysql/plugin.h>, passing thd == NULL
2307 returns the global value of the session variable. */
2308 208095 return std::chrono::seconds{THDVAR(thd, lock_wait_timeout)};
2309 }
2310
2311 /** Is FT ignore stopwords variable set.
2312 @param thd Thread object
2313 @return true if ft_ignore_stopwords is set, false otherwise. */
2314 4207085 bool thd_has_ft_ignore_stopwords(THD *thd) noexcept {
2315 4207085 return (THDVAR(thd, ft_ignore_stopwords));
2316 }
2317
2318 20670 void thd_set_lock_wait_time(THD *thd,
2319 std::chrono::steady_clock::duration value) {
2320
1/2
✓ Branch 0 taken 20670 times.
✗ Branch 1 not taken.
20670 if (thd) {
2321
1/2
✓ Branch 0 taken 20670 times.
✗ Branch 1 not taken.
20670 thd_storage_lock_wait(
2322 thd,
2323 41340 std::chrono::duration_cast<std::chrono::microseconds>(value).count());
2324 }
2325 20670 }
2326
2327 100067 const char *thd_innodb_tmpdir(THD *thd) {
2328 #ifdef UNIV_DEBUG
2329
2/2
✓ Branch 0 taken 100013 times.
✓ Branch 1 taken 54 times.
100067 if (thd != nullptr) {
2330
1/2
✓ Branch 0 taken 100013 times.
✗ Branch 1 not taken.
100013 auto trx = thd_to_trx(thd);
2331
2332 100013 btrsea_sync_check check(trx->has_search_latch);
2333
2334
2/4
✓ Branch 0 taken 100013 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 100013 times.
100013 ut_ad(!sync_check_iterate(check));
2335 100013 }
2336 #endif /* UNIV_DEBUG */
2337
2338 100067 const char *tmp_dir = THDVAR(thd, tmpdir);
2339
2340
3/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 100050 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
100067 if (tmp_dir != nullptr && *tmp_dir == '\0') {
2341 tmp_dir = nullptr;
2342 }
2343
2344 100067 return tmp_dir;
2345 }
2346
2347 /** Obtain the private handler of InnoDB session specific data.
2348 @param[in,out] thd MySQL thread handler.
2349 @return reference to private handler */
2350
2351 3417222772 [[nodiscard]] innodb_session_t *&thd_to_innodb_session(THD *thd) {
2352
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3417222772 times.
3417222772 assert(innodb_hton_ptr->slot != HA_SLOT_UNDEF);
2353
2354 innodb_session_t *&innodb_session =
2355 3417222772 *(innodb_session_t **)thd_ha_data(thd, innodb_hton_ptr);
2356
2357
2/2
✓ Branch 0 taken 3400998259 times.
✓ Branch 1 taken 16234722 times.
3417232981 if (innodb_session != nullptr) {
2358 3400998259 return (innodb_session);
2359 }
2360
2361 16234722 innodb_session = ut::new_withkey<innodb_session_t>(UT_NEW_THIS_FILE_PSI_KEY);
2362 16235129 return (innodb_session);
2363 }
2364
2365 /** Obtain the InnoDB transaction of a MySQL thread.
2366 @param[in,out] thd MySQL thread handler.
2367 @return reference to transaction pointer */
2368
2369 3298746803 [[nodiscard]] trx_t *&thd_to_trx(THD *thd) {
2370 3298746803 innodb_session_t *&innodb_session = thd_to_innodb_session(thd);
2371
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3298757741 times.
3298764987 ut_ad(innodb_session != nullptr);
2372
2373 3298757741 return (innodb_session->m_trx);
2374 }
2375
2376 #ifdef WITH_WSREP
2377
2378 /** Obtain the private handler of InnoDB session specific data.
2379 @param[in,out] thd MySQL thread handler.
2380 @return reference to private handler */
2381 MY_ATTRIBUTE((warn_unused_result))
2382 174 innodb_session_t *&wsrep_thd_to_innodb_session(THD *thd) {
2383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 174 times.
174 assert(innodb_hton_ptr->slot != HA_SLOT_UNDEF);
2384 innodb_session_t *&innodb_session =
2385 174 *(innodb_session_t **)wsrep_thd_ha_data(thd, innodb_hton_ptr);
2386
2387
2/2
✓ Branch 0 taken 147 times.
✓ Branch 1 taken 27 times.
174 if (innodb_session != NULL) {
2388 147 return (innodb_session);
2389 }
2390
2391 /* Ideally, each local transaction executing thread should have
2392 innodb_session already created but there are cases like background
2393 stats update thread that too takes MDL lock creating potential conflict.
2394 Given this is background thread it doesn't have an active transaction
2395 associated with it. */
2396 27 innodb_session = ut::new_withkey<innodb_session_t>(UT_NEW_THIS_FILE_PSI_KEY);
2397 27 return (innodb_session);
2398 }
2399
2400 /** Obtain the InnoDB transaction of a MySQL thread.
2401 @param[in,out] thd MySQL thread handler.
2402 @return reference to transaction pointer */
2403 MY_ATTRIBUTE((warn_unused_result))
2404 174 trx_t *&wsrep_thd_to_trx(THD *thd) {
2405 174 innodb_session_t *&innodb_session = wsrep_thd_to_innodb_session(thd);
2406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 174 times.
174 ut_ad(innodb_session != NULL);
2407
2408 174 return (innodb_session->m_trx);
2409 }
2410
2411 #endif /* WITH_WSREP */
2412
2413 86405 ulong thd_parallel_read_threads(THD *thd) {
2414 86405 return THDVAR(thd, parallel_read_threads);
2415 }
2416
2417 43913 ulong thd_ddl_buffer_size(THD *thd) { return THDVAR(thd, ddl_buffer_size); }
2418
2419 43913 size_t thd_ddl_threads(THD *thd) noexcept { return THDVAR(thd, ddl_threads); }
2420
2421 /** Check if statement is of type INSERT .... SELECT that involves
2422 use of intrinsic tables.
2423 @param[in] user_thd thread handler
2424 @return true if INSERT .... SELECT statement. */
2425 71223696 static inline bool thd_is_ins_sel_stmt(THD *user_thd) {
2426 /* If the session involves use of intrinsic table
2427 and it is trying to fetch the result from non-temporary tables
2428 it indicates "insert .... select" statement. For non-temporary
2429 table this is verifed using the locked tables count but for
2430 intrinsic table as external_lock is not invoked this count is
2431 not updated.
2432
2433 Why is this needed ?
2434 Use of AHI is blocked if statement is insert .... select statement. */
2435 71223696 innodb_session_t *innodb_priv = thd_to_innodb_session(user_thd);
2436 71224456 return (innodb_priv->count_register_table_handler() > 0 ? true : false);
2437 }
2438
2439 #ifdef WITH_WSREP
2440 static int wsrep_abort_transaction_func(handlerton *hton, THD *bf_thd,
2441 THD *victim_thd, bool signal);
2442 static int innobase_wsrep_set_checkpoint(handlerton *hton, const XID *xid);
2443 static int innobase_wsrep_get_checkpoint(handlerton *hton, XID *xid);
2444
2445 #endif /* WITH_WSREP */
2446
2447 /** Add the table handler to thread cache.
2448 Obtain the InnoDB transaction of a MySQL thread.
2449 @param[in,out] table table handler
2450 @param[in,out] heap heap for allocating system columns.
2451 @param[in,out] thd MySQL thread handler */
2452 110975 static inline void add_table_to_thread_cache(dict_table_t *table,
2453 mem_heap_t *heap, THD *thd) {
2454 110975 dict_table_add_system_columns(table, heap);
2455
2456 110975 dict_table_set_big_rows(table);
2457
2458 110975 innodb_session_t *&priv = thd_to_innodb_session(thd);
2459 110975 priv->register_table_handler(table->name.m_name, table);
2460 110975 }
2461
2462 /** Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth
2463 time calls srv_active_wake_master_thread. This function should be used
2464 when a single database operation may introduce a small need for
2465 server utility activity, like checkpointing. */
2466 89003503 inline void innobase_active_small(void) {
2467 89003503 innobase_active_counter++;
2468
2469
2/2
✓ Branch 0 taken 2776580 times.
✓ Branch 1 taken 86226923 times.
89003503 if ((innobase_active_counter % INNOBASE_WAKE_INTERVAL) == 0) {
2470 2776580 srv_active_wake_master_thread();
2471 }
2472 89003506 }
2473
2474 /** Converts an InnoDB error code to a MySQL error code.
2475 Also tells to MySQL about a possible transaction rollback inside InnoDB caused
2476 by a lock wait timeout or a deadlock.
2477 @param[in] error InnoDB error code.
2478 @param[in] flags InnoDB table flags or 0.
2479 @param[in] thd MySQL thread or NULL.
2480 @return MySQL error code */
2481 121239331 int convert_error_code_to_mysql(dberr_t error, uint32_t flags, THD *thd) {
2482
32/48
✓ Branch 0 taken 120167456 times.
✓ Branch 1 taken 55 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 201 times.
✓ Branch 5 taken 1070391 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 485 times.
✓ Branch 11 taken 427 times.
✓ Branch 12 taken 106 times.
✓ Branch 13 taken 89 times.
✓ Branch 14 taken 18 times.
✓ Branch 15 taken 3 times.
✓ Branch 16 taken 22 times.
✓ Branch 17 taken 8 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✓ Branch 22 taken 2 times.
✓ Branch 23 taken 10 times.
✓ Branch 24 taken 13 times.
✓ Branch 25 taken 12 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✓ Branch 28 taken 3 times.
✓ Branch 29 taken 6 times.
✓ Branch 30 taken 10 times.
✓ Branch 31 taken 51 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 12 times.
✓ Branch 34 taken 10 times.
✓ Branch 35 taken 8 times.
✓ Branch 36 taken 8 times.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✓ Branch 39 taken 1 times.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✓ Branch 42 taken 2 times.
✓ Branch 43 taken 55 times.
✓ Branch 44 taken 3 times.
✓ Branch 45 taken 1 times.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
121239331 switch (error) {
2483 120167456 case DB_SUCCESS:
2484 120167456 return (0);
2485
2486 55 case DB_INTERRUPTED:
2487
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 54 times.
55 thd_set_kill_status(thd != nullptr ? thd : current_thd);
2488 55 return (HA_ERR_GENERIC);
2489
2490 1 case DB_FOREIGN_EXCEED_MAX_CASCADE:
2491
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 ut_ad(thd);
2492 1 my_error(ER_FK_DEPTH_EXCEEDED, MYF(0), FK_MAX_CASCADE_DEL);
2493 1 return (HA_ERR_FK_DEPTH_EXCEEDED);
2494
2495 case DB_CANT_CREATE_GEOMETRY_OBJECT:
2496 my_error(ER_CANT_CREATE_GEOMETRY_OBJECT, MYF(0));
2497 return (HA_ERR_NULL_IN_SPATIAL);
2498
2499 201 case DB_ERROR:
2500 default:
2501 201 return (HA_ERR_GENERIC); /* unspecified error */
2502
2503 1070391 case DB_DUPLICATE_KEY:
2504 /* Be cautious with returning this error, since
2505 mysql could re-enter the storage layer to get
2506 duplicated key info, the operation requires a
2507 valid table handle and/or transaction information,
2508 which might not always be available in the error
2509 handling stage. */
2510 1070391 return (HA_ERR_FOUND_DUPP_KEY);
2511
2512 4 case DB_READ_ONLY:
2513
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (srv_force_recovery) {
2514 4 return (HA_ERR_INNODB_FORCED_RECOVERY);
2515 }
2516 return (HA_ERR_TABLE_READONLY);
2517
2518 4 case DB_FOREIGN_DUPLICATE_KEY:
2519 4 return (HA_ERR_FOREIGN_DUPLICATE_KEY);
2520
2521 case DB_MISSING_HISTORY:
2522 return (HA_ERR_TABLE_DEF_CHANGED);
2523
2524 case DB_RECORD_NOT_FOUND:
2525 return (HA_ERR_NO_ACTIVE_RECORD);
2526
2527 485 case DB_FORCED_ABORT:
2528 case DB_DEADLOCK:
2529 /* Since we rolled back the whole transaction, we must
2530 tell it also to MySQL so that MySQL knows to empty the
2531 cached binlog for this transaction */
2532
2533
1/2
✓ Branch 0 taken 485 times.
✗ Branch 1 not taken.
485 if (thd != nullptr) {
2534 485 thd_mark_transaction_to_rollback(thd, 1);
2535 }
2536
2537 485 return (HA_ERR_LOCK_DEADLOCK);
2538
2539 427 case DB_LOCK_WAIT_TIMEOUT:
2540 /* Starting from 5.0.13, we let MySQL just roll back the
2541 latest SQL statement in a lock wait timeout. Previously, we
2542 rolled back the whole transaction. */
2543
2544
1/2
✓ Branch 0 taken 427 times.
✗ Branch 1 not taken.
427 if (thd) {
2545 427 thd_mark_transaction_to_rollback(thd, (int)row_rollback_on_timeout);
2546 }
2547
2548 428 return (HA_ERR_LOCK_WAIT_TIMEOUT);
2549
2550 106 case DB_NO_REFERENCED_ROW:
2551 106 return (HA_ERR_NO_REFERENCED_ROW);
2552
2553 89 case DB_ROW_IS_REFERENCED:
2554 89 return (HA_ERR_ROW_IS_REFERENCED);
2555
2556 18 case DB_NO_FK_ON_S_BASE_COL:
2557 case DB_CANNOT_ADD_CONSTRAINT:
2558 case DB_CHILD_NO_INDEX:
2559 case DB_PARENT_NO_INDEX:
2560 18 return (HA_ERR_CANNOT_ADD_FOREIGN);
2561
2562 3 case DB_CANNOT_DROP_CONSTRAINT:
2563
2564 3 return (HA_ERR_ROW_IS_REFERENCED); /* TODO: This is a bit
2565 misleading, a new MySQL error
2566 code should be introduced */
2567
2568 22 case DB_CORRUPTION:
2569 22 return (HA_ERR_CRASHED);
2570
2571 8 case DB_OUT_OF_FILE_SPACE:
2572 8 return (HA_ERR_RECORD_FILE_FULL);
2573
2574 case DB_OUT_OF_DISK_SPACE:
2575 return (HA_ERR_DISK_FULL_NOWAIT);
2576
2577 case DB_TEMP_FILE_WRITE_FAIL:
2578 return (HA_ERR_TEMP_FILE_WRITE_FAILURE);
2579
2580 case DB_TABLE_IN_FK_CHECK:
2581 return (HA_ERR_TABLE_IN_FK_CHECK);
2582
2583 case DB_TABLE_IS_BEING_USED:
2584 return (HA_ERR_WRONG_COMMAND);
2585
2586 2 case DB_TABLE_NOT_FOUND:
2587 2 return (HA_ERR_NO_SUCH_TABLE);
2588
2589 10 case DB_TABLESPACE_NOT_FOUND:
2590 10 return (HA_ERR_TABLESPACE_MISSING);
2591
2592 13 case DB_TOO_BIG_RECORD: {
2593 /* If prefix is true then a 768-byte prefix is stored
2594 locally for BLOB fields. Refer to dict_table_get_format().
2595 We limit max record size to 16k for 64k page size. */
2596 13 bool prefix = !DICT_TF_HAS_ATOMIC_BLOBS(flags);
2597
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 11 times.
26 my_printf_error(
2598 ER_TOO_BIG_ROWSIZE,
2599 "Row size too large (> %lu). Changing some columns"
2600 " to TEXT or BLOB %smay help. In current row"
2601 " format, BLOB prefix of %d bytes is stored inline.",
2602 MYF(0),
2603
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 srv_page_size == UNIV_PAGE_SIZE_MAX
2604 ? REC_MAX_DATA_SIZE - 1
2605 13 : page_get_free_space_of_empty(flags & DICT_TF_COMPACT) / 2,
2606 prefix ? "or using ROW_FORMAT=DYNAMIC or"
2607 " ROW_FORMAT=COMPRESSED "
2608 : "",
2609 prefix ? DICT_MAX_FIXED_COL_LEN : 0);
2610 13 return (HA_ERR_TOO_BIG_ROW);
2611 }
2612
2613 12 case DB_TOO_BIG_INDEX_COL:
2614 12 my_error(ER_INDEX_COLUMN_TOO_LONG, MYF(0),
2615 DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags));
2616 12 return (HA_ERR_INDEX_COL_TOO_LONG);
2617
2618 case DB_NO_SAVEPOINT:
2619 return (HA_ERR_NO_SAVEPOINT);
2620
2621 case DB_LOCK_TABLE_FULL:
2622 /* Since we rolled back the whole transaction, we must
2623 tell it also to MySQL so that MySQL knows to empty the
2624 cached binlog for this transaction */
2625
2626 if (thd) {
2627 thd_mark_transaction_to_rollback(thd, 1);
2628 }
2629
2630 return (HA_ERR_LOCK_TABLE_FULL);
2631
2632 3 case DB_FTS_INVALID_DOCID:
2633 3 return (HA_FTS_INVALID_DOCID);
2634 6 case DB_FTS_EXCEED_RESULT_CACHE_LIMIT:
2635 6 return (HA_ERR_FTS_EXCEED_RESULT_CACHE_LIMIT);
2636 10 case DB_TOO_MANY_CONCURRENT_TRXS:
2637 10 return (HA_ERR_TOO_MANY_CONCURRENT_TRXS);
2638 51 case DB_UNSUPPORTED:
2639 51 return (HA_ERR_UNSUPPORTED);
2640 case DB_INDEX_CORRUPT:
2641 return (HA_ERR_INDEX_CORRUPT);
2642 12 case DB_UNDO_RECORD_TOO_BIG:
2643 12 return (HA_ERR_UNDO_REC_TOO_BIG);
2644 10 case DB_OUT_OF_MEMORY:
2645 10 return (HA_ERR_OUT_OF_MEM);
2646 8 case DB_TABLESPACE_EXISTS:
2647 8 return (HA_ERR_TABLESPACE_EXISTS);
2648 8 case DB_TABLESPACE_DELETED:
2649 8 return (HA_ERR_TABLESPACE_MISSING);
2650 case DB_IDENTIFIER_TOO_LONG:
2651 return (HA_ERR_INTERNAL_ERROR);
2652 case DB_TOO_LONG_PATH:
2653 return (HA_ERR_TOO_LONG_PATH);
2654 1 case DB_TABLE_CORRUPT:
2655 1 return (HA_ERR_TABLE_CORRUPT);
2656 case DB_FTS_TOO_MANY_WORDS_IN_PHRASE:
2657 return (HA_ERR_FTS_TOO_MANY_WORDS_IN_PHRASE);
2658 case DB_WRONG_FILE_NAME:
2659 return (HA_ERR_WRONG_FILE_NAME);
2660 2 case DB_COMPUTE_VALUE_FAILED:
2661 2 return (HA_ERR_COMPUTE_FAILED);
2662 55 case DB_LOCK_NOWAIT:
2663 55 my_error(ER_LOCK_NOWAIT, MYF(0));
2664 55 return (HA_ERR_NO_WAIT_LOCK);
2665 3 case DB_NO_SESSION_TEMP:
2666 3 return (HA_ERR_NO_SESSION_TEMP);
2667 1 case DB_BTREE_LEVEL_LIMIT_EXCEEDED:
2668 1 return (HA_ERR_INTERNAL_ERROR);
2669 case DB_FTS_TOO_MANY_NESTED_EXP:
2670 return (HA_ERR_FTS_TOO_MANY_NESTED_EXP);
2671 case DB_IO_NO_PUNCH_HOLE:
2672 case DB_IO_NO_PUNCH_HOLE_FS:
2673 case DB_IO_NO_PUNCH_HOLE_TABLESPACE:
2674 return HA_ERR_UNSUPPORTED;
2675 }
2676 }
2677
2678 /** Prints info of a THD object (== user session thread) to the given file. */
2679 623 void innobase_mysql_print_thd(
2680 FILE *f, /*!< in: output stream */
2681 THD *thd, /*!< in: MySQL THD object */
2682 uint max_query_len) /*!< in: max query length to print, or 0 to
2683 use the default max length */
2684 {
2685 char buffer[1024];
2686
2687
2/4
✓ Branch 0 taken 623 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 623 times.
✗ Branch 3 not taken.
623 fputs(thd_security_context(thd, buffer, sizeof buffer, max_query_len), f);
2688
1/2
✓ Branch 0 taken 623 times.
✗ Branch 1 not taken.
623 putc('\n', f);
2689 623 }
2690
2691 /** Get the error message format string.
2692 @return the format string or 0 if not found. */
2693 9020 const char *innobase_get_err_msg(int error_code) /*!< in: MySQL error code */
2694 {
2695 9020 return (my_get_err_msg(error_code));
2696 }
2697
2698 /** Get the variable length bounds of the given character set.
2699 @param[in] cset Mysql charset-collation code
2700 @param[out] mbminlen Minimum length of a char (in bytes)
2701 @param[out] mbmaxlen Maximum length of a char (in bytes) */
2702 73890160 void innobase_get_cset_width(ulint cset, ulint *mbminlen, ulint *mbmaxlen) {
2703 CHARSET_INFO *cs;
2704
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73885613 times.
73890160 ut_ad(cset <= MAX_CHAR_COLL_NUM);
2705
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73876757 times.
73885613 ut_ad(mbminlen);
2706
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73875138 times.
73876757 ut_ad(mbmaxlen);
2707
2708 73875138 cs = all_charsets[cset];
2709
2/2
✓ Branch 0 taken 16272774 times.
✓ Branch 1 taken 57602364 times.
73875138 if (cs) {
2710 16272774 *mbminlen = cs->mbminlen;
2711 16272774 *mbmaxlen = cs->mbmaxlen;
2712
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16272766 times.
16272774 ut_ad(*mbminlen < DATA_MBMAX);
2713
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16272790 times.
16272766 ut_ad(*mbmaxlen < DATA_MBMAX);
2714 } else {
2715 57602364 THD *thd = current_thd;
2716
2717
6/6
✓ Branch 0 taken 50563844 times.
✓ Branch 1 taken 7038730 times.
✓ Branch 2 taken 495215 times.
✓ Branch 3 taken 50068734 times.
✓ Branch 4 taken 495215 times.
✓ Branch 5 taken 57107464 times.
57602574 if (thd && thd_sql_command(thd) == SQLCOM_DROP_TABLE) {
2718 /* Fix bug#46256: allow tables to be dropped if the
2719 collation is not found, but issue a warning. */
2720
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 495215 times.
495215 if (cset != 0) {
2721 log_errlog(ERROR_LEVEL, ER_INNODB_UNKNOWN_COLLATION);
2722 }
2723 } else {
2724
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57105299 times.
57107464 ut_a(cset == 0);
2725 }
2726
2727 57602262 *mbminlen = *mbmaxlen = 0;
2728 }
2729 73875052 }
2730
2731 /**********************************************************************
2732 Check if the length of the identifier exceeds the maximum allowed.
2733 return true when length of identifier is too long. */
2734 292 bool innobase_check_identifier_length(
2735 const char *id) /* in: FK identifier to check excluding the
2736 database portion. */
2737 {
2738 292 int well_formed_error = 0;
2739 292 CHARSET_INFO *cs = system_charset_info;
2740
1/2
✓ Branch 0 taken 292 times.
✗ Branch 1 not taken.
292 DBUG_TRACE;
2741
2742
1/2
✓ Branch 0 taken 292 times.
✗ Branch 1 not taken.
292 size_t len = cs->cset->well_formed_len(cs, id, id + strlen(id), NAME_CHAR_LEN,
2743 &well_formed_error);
2744
2745
2/4
✓ Branch 0 taken 292 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 292 times.
292 if (well_formed_error || len != strlen(id)) {
2746 my_error(ER_TOO_LONG_IDENT, MYF(0), id);
2747 return true;
2748 }
2749 292 return false;
2750 292 }
2751 #endif /* !UNIV_HOTBACKUP */
2752
2753 /** Compares NUL-terminated UTF-8 strings case insensitively.
2754 @return 0 if a=b, <0 if a\<b, >1 if a>b */
2755 30101033 int innobase_strcasecmp(const char *a, /*!< in: first string to compare */
2756 const char *b) /*!< in: second string to compare */
2757 {
2758
2/2
✓ Branch 0 taken 1067377 times.
✓ Branch 1 taken 29033656 times.
30101033 if (!a) {
2759
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1067377 times.
1067377 if (!b) {
2760 return (0);
2761 } else {
2762 1067377 return (-1);
2763 }
2764
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29033656 times.
29033656 } else if (!b) {
2765 return (1);
2766 }
2767
2768 29033656 return (my_strcasecmp(system_charset_info, a, b));
2769 }
2770
2771 #ifndef UNIV_HOTBACKUP
2772 /** Compares NUL-terminated UTF-8 strings case insensitively. The
2773 second string contains wildcards.
2774 @return 0 if a match is found, 1 if not */
2775 23959 static int innobase_wildcasecmp(
2776 const char *a, /*!< in: string to compare */
2777 const char *b) /*!< in: wildcard string to compare */
2778 {
2779 23959 return (wild_case_compare(system_charset_info, a, b));
2780 }
2781 #endif /* !UNIV_HOTBACKUP */
2782
2783 /** Strip dir name from a full path name and return only the file name
2784 @param[in] path_name full path name
2785 @return file name or "null" if no file name */
2786 141 const char *innobase_basename(const char *path_name) {
2787 141 const char *name = base_name(path_name);
2788
2789
1/2
✓ Branch 0 taken 141 times.
✗ Branch 1 not taken.
141 return ((name) ? name : "null");
2790 }
2791
2792 #ifndef UNIV_HOTBACKUP
2793
2794 /** Makes all characters in a NUL-terminated UTF-8 string lower case. */
2795 1104573 void innobase_casedn_str(char *a) /*!< in/out: string to put in lower case */
2796 {
2797 1104573 my_casedn_str(system_charset_info, a);
2798 1104589 }
2799
2800 /** Makes all characters in a NUL-terminated UTF-8 path string lower case. */
2801 30 void innobase_casedn_path(char *a) /*!< in/out: string to put in lower case */
2802 {
2803 30 my_casedn_str(&my_charset_filename, a);
2804 30 }
2805
2806 /** Determines the connection character set.
2807 @return connection character set */
2808 59 const CHARSET_INFO *innobase_get_charset(
2809 THD *mysql_thd) /*!< in: MySQL thread handle */
2810 {
2811 59 return (thd_charset(mysql_thd));
2812 }
2813
2814 /** Determines the current SQL statement.
2815 Thread unsafe, can only be called from the thread owning the THD.
2816 @param[in] thd MySQL thread handle
2817 @param[out] length Length of the SQL statement
2818 @return SQL statement string */
2819 347994 const char *innobase_get_stmt_unsafe(THD *thd, size_t *length) {
2820 LEX_CSTRING stmt;
2821
2822
1/2
✓ Branch 0 taken 347994 times.
✗ Branch 1 not taken.
347994 stmt = thd_query_unsafe(thd);
2823 347994 *length = stmt.length;
2824 347994 return (stmt.str);
2825 }
2826
2827 /** Determines the current SQL statement.
2828 Thread safe, can be called from any thread as the string is copied
2829 into the provided buffer.
2830 @param[in] thd MySQL thread handle
2831 @param[out] buf Buffer containing SQL statement
2832 @param[in] buflen Length of provided buffer
2833 @return Length of the SQL statement */
2834 74 size_t innobase_get_stmt_safe(THD *thd, char *buf, size_t buflen) {
2835 74 return (thd_query_safe(thd, buf, buflen));
2836 }
2837
2838 /** Get the current setting of the table_def_size global parameter. We do
2839 a dirty read because for one there is no synchronization object and
2840 secondly there is little harm in doing so even if we get a torn read.
2841 @return value of table_def_size */
2842 206064 ulint innobase_get_table_cache_size(void) { return (table_def_size); }
2843
2844 /** Get the current setting of the lower_case_table_names global parameter from
2845 mysqld.cc. We do a dirty read because for one there is no synchronization
2846 object and secondly there is little harm in doing so even if we get a torn
2847 read.
2848 @return value of lower_case_table_names */
2849 29845993 ulint innobase_get_lower_case_table_names(void) {
2850 29845993 return (lower_case_table_names);
2851 }
2852
2853 19200 char *innobase_mysql_tmpdir() { return (mysql_tmpdir); }
2854
2855 67382 os_fd_t innobase_mysql_tmpfile(const char *path) {
2856
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 67382 times.
67382 DBUG_EXECUTE_IF("innobase_tmpfile_creation_failure", return (-1););
2857
2858 #ifdef WITH_WSREP
2859 67382 os_event_wait(srv_allow_writes_event);
2860 #endif /* WITH_WSREP */
2861
2862 auto fd =
2863
2/2
✓ Branch 0 taken 9645 times.
✓ Branch 1 taken 57743 times.
67388 (path == nullptr) ? mysql_tmpfile("ib") : mysql_tmpfile_path(path, "ib");
2864
2865 67388 os_fd_t fd2{OS_FD_CLOSED};
2866
2867
2/2
✓ Branch 0 taken 67387 times.
✓ Branch 1 taken 1 times.
67388 if (fd >= 0) {
2868 /* Copy the file descriptor, so that the additional resources
2869 allocated by create_temp_file() can be freed by invoking
2870 my_close().
2871
2872 Because the file descriptor returned by this function
2873 will be passed to fdopen(), it will be closed by invoking
2874 fclose(), which in turn will invoke close() instead of
2875 my_close(). */
2876
2877 #ifdef _WIN32
2878 /* Note that on Windows, the integer returned by mysql_tmpfile
2879 has no relation to C runtime file descriptor. Here, we need
2880 to call my_get_osfhandle to get the HANDLE and then convert it
2881 to C runtime filedescriptor. */
2882 {
2883 HANDLE hDup;
2884
2885 auto hFile = my_get_osfhandle(fd);
2886
2887 auto bOK =
2888 DuplicateHandle(GetCurrentProcess(), hFile, GetCurrentProcess(),
2889 &hDup, 0, false, DUPLICATE_SAME_ACCESS);
2890 if (bOK) {
2891 fd2 = _open_osfhandle((intptr_t)hDup, 0);
2892 } else {
2893 my_osmaperr(GetLastError());
2894 fd2 = OS_FD_CLOSED;
2895 }
2896 }
2897 #else
2898 67387 fd2 = dup(fd);
2899 #endif
2900
2901
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 67386 times.
67386 if (fd2 < 0) {
2902 char errbuf[MYSYS_STRERROR_SIZE];
2903
2904 DBUG_PRINT("error", ("Got error %d on dup", fd2));
2905
2906 set_my_errno(errno);
2907
2908 my_error(EE_OUT_OF_FILERESOURCES, MYF(0), "ib*", my_errno(),
2909 my_strerror(errbuf, sizeof(errbuf), my_errno()));
2910 }
2911
2912 67386 my_close(fd, MYF(MY_WME));
2913 }
2914
2915 67388 return fd2;
2916 }
2917
2918 /** Wrapper around MySQL's copy_and_convert function.
2919 @return number of bytes copied to 'to' */
2920 272 static ulint innobase_convert_string(
2921 void *to, /*!< out: converted string */
2922 ulint to_length, /*!< in: number of bytes reserved
2923 for the converted string */
2924 CHARSET_INFO *to_cs, /*!< in: character set to convert to */
2925 const void *from, /*!< in: string to convert */
2926 ulint from_length, /*!< in: number of bytes to convert */
2927 CHARSET_INFO *from_cs, /*!< in: character set to convert
2928 from */
2929 uint *errors) /*!< out: number of errors encountered
2930 during the conversion */
2931 {
2932 272 return (copy_and_convert((char *)to, (uint32)to_length, to_cs,
2933 (const char *)from, (uint32)from_length, from_cs,
2934 272 errors));
2935 }
2936
2937 /** Formats the raw data in "data" (in InnoDB on-disk format) that is of
2938 type DATA_(CHAR|VARCHAR|MYSQL|VARMYSQL) using "charset_coll" and writes
2939 the result to "buf". The result is converted to "system_charset_info".
2940 Not more than "buf_size" bytes are written to "buf".
2941 The result is always NUL-terminated (provided buf_size > 0) and the
2942 number of bytes that were written to "buf" is returned (including the
2943 terminating NUL).
2944 @return number of bytes that were written */
2945 272 ulint innobase_raw_format(const char *data, /*!< in: raw data */
2946 ulint data_len, /*!< in: raw data length
2947 in bytes */
2948 ulint charset_coll, /*!< in: charset collation */
2949 char *buf, /*!< out: output buffer */
2950 ulint buf_size) /*!< in: output buffer size
2951 in bytes */
2952 {
2953 /* XXX we use a hard limit instead of allocating
2954 but_size bytes from the heap */
2955 CHARSET_INFO *data_cs;
2956 char buf_tmp[8192];
2957 ulint buf_tmp_used;
2958 uint num_errors;
2959
2960 272 data_cs = all_charsets[charset_coll];
2961
2962 buf_tmp_used =
2963
1/2
✓ Branch 0 taken 272 times.
✗ Branch 1 not taken.
272 innobase_convert_string(buf_tmp, sizeof(buf_tmp), system_charset_info,
2964 data, data_len, data_cs, &num_errors);
2965
2966 544 return (ut_str_sql_format(buf_tmp, buf_tmp_used, buf, buf_size));
2967 }
2968
2969 #endif /* !UNIV_HOTBACKUP */
2970
2971 /** Check if the string is "empty" or "none".
2972 @param[in] algorithm Compression algorithm to check
2973 @return true if no algorithm requested */
2974 232097 bool Compression::is_none(const char *algorithm) {
2975 /* NULL is the same as NONE */
2976
5/6
✓ Branch 0 taken 1660 times.
✓ Branch 1 taken 230437 times.
✓ Branch 2 taken 1660 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 231274 times.
✓ Branch 5 taken 823 times.
233757 if (algorithm == nullptr || *algorithm == 0 ||
2977
2/2
✓ Branch 0 taken 837 times.
✓ Branch 1 taken 823 times.
1660 innobase_strcasecmp(algorithm, "none") == 0) {
2978 231274 return (true);
2979 }
2980
2981 823 return (false);
2982 }
2983
2984 /** Check wether the compression algorithm is supported.
2985 @param[in] algorithm Compression algorithm to check
2986 @param[out] compression The type that algorithm maps to
2987 @return DB_SUCCESS or error code */
2988 231558 dberr_t Compression::check(const char *algorithm, Compression *compression) {
2989
2/2
✓ Branch 0 taken 230739 times.
✓ Branch 1 taken 819 times.
231558 if (is_none(algorithm)) {
2990 230739 compression->m_type = NONE;
2991
2992
2/2
✓ Branch 0 taken 271 times.
✓ Branch 1 taken 548 times.
819 } else if (innobase_strcasecmp(algorithm, "zlib") == 0) {
2993 271 compression->m_type = ZLIB;
2994
2995
2/2
✓ Branch 0 taken 540 times.
✓ Branch 1 taken 8 times.
548 } else if (innobase_strcasecmp(algorithm, "lz4") == 0) {
2996 540 compression->m_type = LZ4;
2997
2998 } else {
2999 8 return (DB_UNSUPPORTED);
3000 }
3001
3002 231550 return (DB_SUCCESS);
3003 }
3004
3005 /** Validate the algorithm string.
3006 @param[in] algorithm Compression algorithm to check
3007 @return DB_SUCCESS or error code */
3008 230623 dberr_t Compression::validate(const char *algorithm) {
3009 230623 Compression compression;
3010
3011
1/2
✓ Branch 0 taken 230623 times.
✗ Branch 1 not taken.
461246 return (check(algorithm, &compression));
3012 }
3013
3014 580 bool Compression::validate(const Compression::Type type) {
3015 580 bool ret = true;
3016
3017
1/2
✓ Branch 0 taken 580 times.
✗ Branch 1 not taken.
580 switch (type) {
3018 580 case NONE:
3019 case ZLIB:
3020 case LZ4:
3021 580 break;
3022 default:
3023 ret = false;
3024 break;
3025 }
3026
3027 580 return ret;
3028 }
3029
3030 #ifndef UNIV_HOTBACKUP
3031 1597041 bool Encryption::is_empty(const char *algorithm) noexcept {
3032 /* nullptr is the same as empty */
3033 1597041 return algorithm == nullptr;
3034 }
3035
3036 1597042 bool Encryption::is_none(const char *algorithm) noexcept {
3037
2/2
✓ Branch 0 taken 1285305 times.
✓ Branch 1 taken 311736 times.
2882348 return Encryption::is_empty(algorithm) ||
3038
2/2
✓ Branch 0 taken 1264884 times.
✓ Branch 1 taken 20422 times.
2882347 innobase_strcasecmp(algorithm, "n") == 0;
3039 }
3040
3041 /** Check if the string is "y" or "Y".
3042 @param[in] algorithm Encryption algorithm to check
3043 @return true if no algorithm requested */
3044 1521302 bool Encryption::is_master_key_encryption(const char *algorithm) noexcept {
3045 1521302 return innobase_strcasecmp(algorithm, "y") == 0;
3046 }
3047
3048 /** Check if the NO algorithm was explicitly specified.
3049 @param[in] algorithm Encryption algorithm to check
3050 @return true if no algorithm explicitly requested */
3051 1507607 bool Encryption::none_explicitly_specified(bool explicit_encryption,
3052 const char *algorithm) noexcept {
3053
2/2
✓ Branch 0 taken 269304 times.
✓ Branch 1 taken 1238303 times.
1507607 if (explicit_encryption) {
3054
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 269304 times.
269304 ut_ad(algorithm != nullptr);
3055 269304 return innobase_strcasecmp(algorithm, "n") == 0;
3056 }
3057 1238303 return false;
3058 }
3059
3060 1548213 bool Encryption::is_keyring(const char *algoritm) noexcept {
3061
3/4
✓ Branch 0 taken 480852 times.
✓ Branch 1 taken 1067361 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 480852 times.
1548213 return (algoritm != nullptr && innobase_strcasecmp(algoritm, "keyring") == 0);
3062 }
3063
3064 910306 bool Encryption::is_online_encryption_on() noexcept {
3065 910306 return srv_default_table_encryption == DEFAULT_TABLE_ENC_ONLINE_TO_KEYRING;
3066 }
3067
3068 // This for now excludes MK encryption ...
3069 637316 bool Encryption::should_be_keyring_encrypted(bool explicit_encryption,
3070 const char *algorithm) noexcept {
3071
3/4
✓ Branch 0 taken 577935 times.
✓ Branch 1 taken 59381 times.
✓ Branch 2 taken 577935 times.
✗ Branch 3 not taken.
1793186 return !none_explicitly_specified(explicit_encryption, algorithm) &&
3072 577935 (is_keyring(algorithm) ||
3073
4/4
✓ Branch 0 taken 572186 times.
✓ Branch 1 taken 5749 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 572181 times.
1150121 (!Encryption::is_master_key_encryption(algorithm) &&
3074 1209502 is_online_encryption_on()));
3075 }
3076
3077 278763 dberr_t Encryption::set_algorithm(const char *option,
3078 Encryption *encryption) noexcept {
3079
2/2
✓ Branch 0 taken 266939 times.
✓ Branch 1 taken 11826 times.
278763 if (is_none(option)) {
3080 266939 encryption->m_type = NONE;
3081
3082
2/2
✓ Branch 0 taken 11750 times.
✓ Branch 1 taken 76 times.
11826 } else if (innobase_strcasecmp(option, "y") == 0) {
3083 11750 encryption->m_type = AES;
3084
3085
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
76 } else if (innobase_strcasecmp(option, "KEYRING") == 0) {
3086 #ifdef WITH_WSREP
3087 return (DB_UNSUPPORTED);
3088 #else
3089 encryption->m_type = KEYRING;
3090 #endif
3091
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
76 } else if (innobase_strcasecmp(option, "ONLINE_TO_KEYRING") == 0) {
3092 #ifdef WITH_WSREP
3093 return (DB_UNSUPPORTED);
3094 #else
3095 encryption->m_type = KEYRING;
3096 #endif
3097 } else {
3098 76 return (DB_UNSUPPORTED);
3099 }
3100
3101 278689 return (DB_SUCCESS);
3102 }
3103
3104 277386 dberr_t Encryption::validate(const char *option) noexcept {
3105 277386 Encryption encryption;
3106
3107 277388 return (encryption.set_algorithm(option, &encryption));
3108 277389 }
3109
3110 /** Check for supported ENCRYPT := (Y | N) supported values
3111 @param[in] option Encryption option
3112 @return DB_SUCCESS or DB_UNSUPPORTED */
3113 1376 dberr_t Encryption::validate_for_tablespace(const char *option) noexcept {
3114
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1376 times.
1376 if (innobase_strcasecmp(option, "KEYRING") == 0) {
3115 return DB_UNSUPPORTED;
3116 }
3117
3118 1376 Encryption encryption;
3119
3120 1376 return (encryption.set_algorithm(option, &encryption));
3121 1376 }
3122 /** Compute the next autoinc value.
3123
3124 For MySQL replication the autoincrement values can be partitioned among
3125 the nodes. The offset is the start or origin of the autoincrement value
3126 for a particular node. For n nodes the increment will be n and the offset
3127 will be in the interval [1, n]. The formula tries to allocate the next
3128 value for a particular node.
3129
3130 Note: This function is also called with increment set to the number of
3131 values we want to reserve for multi-value inserts e.g.,
3132
3133 INSERT INTO T VALUES(), (), ();
3134
3135 innobase_next_autoinc() will be called with increment set to 3 where
3136 autoinc_lock_mode != TRADITIONAL because we want to reserve 3 values for
3137 the multi-value INSERT above.
3138 @return the next value */
3139 9234449 ulonglong innobase_next_autoinc(
3140 ulonglong current, /*!< in: Current value */
3141 ulonglong need, /*!< in: count of values needed */
3142 ulonglong step, /*!< in: AUTOINC increment step */
3143 ulonglong offset, /*!< in: AUTOINC offset */
3144 ulonglong max_value) /*!< in: max value for type */
3145 {
3146 ulonglong next_value;
3147 9234449 ulonglong block = need * step;
3148
3149 /* Should never be 0. */
3150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9234486 times.
9234449 ut_a(need > 0);
3151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9234535 times.
9234486 ut_a(block > 0);
3152
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 9234521 times.
9234535 ut_a(max_value > 0);
3153
3154 /* According to MySQL documentation, if the offset is greater than
3155 the step then the offset is ignored. */
3156
2/2
✓ Branch 0 taken 10990 times.
✓ Branch 1 taken 9223531 times.
9234521 if (offset > block) {
3157 10990 offset = 0;
3158 }
3159
3160 /* Check for overflow. Current can be > max_value if the value is
3161 in reality a negative value.The visual studio compilers converts
3162 large double values automatically into unsigned long long datatype
3163 maximum value */
3164
3165
4/6
✓ Branch 0 taken 9234531 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9234540 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9234451 times.
✓ Branch 5 taken 89 times.
9234521 if (block >= max_value || offset > max_value || current >= max_value ||
3166
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 9234426 times.
9234451 max_value - offset <= offset) {
3167 95 next_value = max_value;
3168 } else {
3169
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 9234436 times.
9234426 ut_a(max_value > current);
3170
3171 9234436 ulonglong free = max_value - current;
3172
3173
4/4
✓ Branch 0 taken 9234423 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 9234419 times.
9234436 if (free < offset || free - offset <= block) {
3174 17 next_value = max_value;
3175 } else {
3176 9234419 next_value = 0;
3177 }
3178 }
3179
3180
2/2
✓ Branch 0 taken 9234405 times.
✓ Branch 1 taken 126 times.
9234531 if (next_value == 0) {
3181 ulonglong next;
3182
3183
2/2
✓ Branch 0 taken 9185656 times.
✓ Branch 1 taken 48749 times.
9234405 if (current > offset) {
3184 9185656 next = (current - offset) / step;
3185 } else {
3186 48749 next = (offset - current) / step;
3187 }
3188
3189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9234413 times.
9234405 ut_a(max_value > next);
3190 9234413 next_value = next * step;
3191 /* Check for multiplication overflow. */
3192
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9234440 times.
9234413 ut_a(next_value >= next);
3193
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 9234428 times.
9234440 ut_a(max_value > next_value);
3194
3195 /* Check for overflow */
3196
1/2
✓ Branch 0 taken 9234428 times.
✗ Branch 1 not taken.
9234428 if (max_value - next_value >= block) {
3197 9234428 next_value += block;
3198
3199
1/2
✓ Branch 0 taken 9234454 times.
✗ Branch 1 not taken.
9234428 if (max_value - next_value >= offset) {
3200 9234454 next_value += offset;
3201 } else {
3202 next_value = max_value;
3203 }
3204 } else {
3205 next_value = max_value;
3206 }
3207 }
3208
3209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9234564 times.
9234554 ut_a(next_value != 0);
3210
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 9234556 times.
9234564 ut_a(next_value <= max_value);
3211
3212 9234556 return (next_value);
3213 }
3214
3215 /**
3216 Check whether given connection should log stats for slow query log InnoDB
3217 extensions.
3218
3219 @param[in] thd connection handle
3220 @return whether stats for slow query log InnoDB extensions should be logged
3221 */
3222 2503566187 static bool innobase_slow_log_verbose(THD *thd) noexcept {
3223
4/4
✓ Branch 0 taken 2096953141 times.
✓ Branch 1 taken 390288043 times.
✓ Branch 2 taken 152690 times.
✓ Branch 3 taken 2096807714 times.
4584205600 return thd && thd_opt_slow_log() &&
3224
2/2
✓ Branch 0 taken 2487245196 times.
✓ Branch 1 taken 16320991 times.
7087767775 unlikely(thd_log_slow_verbosity(thd) & (1ULL << SLOG_V_INNODB)) &&
3225
2/2
✓ Branch 0 taken 146822 times.
✓ Branch 1 taken 5868 times.
2503722128 !thd_is_background_thread(thd);
3226 }
3227
3228 /** Initializes some fields in an InnoDB transaction object. */
3229 1316788242 static void innobase_trx_init(
3230 THD *thd, /*!< in: user thread handle */
3231 trx_t *trx) /*!< in/out: InnoDB transaction handle */
3232 {
3233
1/2
✓ Branch 0 taken 1316801663 times.
✗ Branch 1 not taken.
1316788242 DBUG_TRACE;
3234
2/4
✓ Branch 0 taken 1316801623 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1316801623 times.
1316801663 assert(EQ_CURRENT_THD(thd));
3235
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1316801623 times.
1316801623 assert(thd == trx->mysql_thd);
3236
3237
1/2
✓ Branch 0 taken 1316800546 times.
✗ Branch 1 not taken.
1316801623 trx->check_foreigns = !thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS);
3238
3239 1316799592 trx->check_unique_secondary =
3240
1/2
✓ Branch 0 taken 1316799592 times.
✗ Branch 1 not taken.
1316800546 !thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS);
3241
3242 1316799592 trx->stats.set(innobase_slow_log_verbose(thd));
3243 1316795190 }
3244
3245 /** Allocates an InnoDB transaction for a MySQL handler object for DML.
3246 @return InnoDB transaction handle */
3247 15667562 trx_t *innobase_trx_allocate(THD *thd) /*!< in: user thread handle */
3248 {
3249 trx_t *trx;
3250
3251
1/2
✓ Branch 0 taken 15667587 times.
✗ Branch 1 not taken.
15667562 DBUG_TRACE;
3252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15667587 times.
15667587 assert(thd != nullptr);
3253
2/4
✓ Branch 0 taken 15667589 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15667589 times.
15667587 assert(EQ_CURRENT_THD(thd));
3254
3255 15667589 MONITOR_ATOMIC_INC(MONITOR_TRX_ALLOCATIONS);
3256
1/2
✓ Branch 0 taken 15667593 times.
✗ Branch 1 not taken.
15667572 trx = trx_allocate_for_mysql();
3257
3258
1/2
✓ Branch 0 taken 15667593 times.
✗ Branch 1 not taken.
15667593 rw_lock_s_lock(&purge_sys->latch, UT_LOCATION_HERE);
3259
3260
3/4
✓ Branch 0 taken 15667591 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14781 times.
✓ Branch 3 taken 15652812 times.
15667593 if (purge_sys->thds.find(thd) != purge_sys->thds.end()) {
3261 14781 trx->purge_sys_trx = true;
3262 }
3263
3264
1/2
✓ Branch 0 taken 15667593 times.
✗ Branch 1 not taken.
15667593 rw_lock_s_unlock(&purge_sys->latch);
3265
3266 15667593 trx->mysql_thd = thd;
3267
3268
1/2
✓ Branch 0 taken 15667593 times.
✗ Branch 1 not taken.
15667593 innobase_trx_init(thd, trx);
3269
3270 15667592 return trx;
3271 15667593 }
3272
3273 /** Gets the InnoDB transaction handle for a MySQL handler object, creates
3274 an InnoDB transaction struct if the corresponding MySQL thread struct still
3275 lacks one.
3276 @return InnoDB transaction handle */
3277 1316791124 trx_t *check_trx_exists(THD *thd) /*!< in: user thread handle */
3278 {
3279 /* We request to stop master thread in srv_shutdown, which is invoked
3280 after DD has been shut down. Since that point of time, we must not need
3281 transaction objects for any reasons. */
3282
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1316789871 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1316787766 times.
2633580995 ut_ad(srv_shutdown_state_matches([](auto state) {
3283 return state < SRV_SHUTDOWN_MASTER_STOP ||
3284 state == SRV_SHUTDOWN_EXIT_THREADS;
3285 }));
3286
3287 1316787766 trx_t *&trx = thd_to_trx(thd);
3288
3289
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1316789586 times.
1316789348 ut_ad(EQ_CURRENT_THD(thd));
3290
3291
2/2
✓ Branch 0 taken 15667240 times.
✓ Branch 1 taken 1301122346 times.
1316789586 if (trx == nullptr) {
3292 15667240 trx = innobase_trx_allocate(thd);
3293
3294 /* User trx can be forced to rollback,
3295 so we unset the disable flag. */
3296
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15667249 times.
15667248 ut_ad(trx->in_innodb & TRX_FORCE_ROLLBACK_DISABLE);
3297
3298 15667249 trx->in_innodb &= TRX_FORCE_ROLLBACK_MASK;
3299
3300 } else {
3301
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1301121470 times.
1301122346 ut_a(trx->magic_n == TRX_MAGIC_N);
3302
3303 1301121470 innobase_trx_init(thd, trx);
3304 }
3305
3306 1316801134 return (trx);
3307 }
3308
3309 /** Get the transaction of the current connection handle, if either exists.
3310 @return transaction of the current connection handle, or NULL. */
3311 trx_t *innobase_get_trx(void) {
3312 THD *const thd = current_thd;
3313 if (UNIV_UNLIKELY(!thd)) return (nullptr);
3314
3315 return (thd_to_trx(thd));
3316 }
3317
3318 /** Get the transaction of the current connection handle if slow query log
3319 InnoDB extended statistics should be collected.
3320 @return transaction object if statistics should be collected, or NULL. */
3321 1186785948 trx_t *innobase_get_trx_for_slow_log(void) noexcept {
3322 1186785948 THD *thd = current_thd;
3323
2/2
✓ Branch 0 taken 1186749191 times.
✓ Branch 1 taken 43810 times.
1186791614 if (UNIV_LIKELY(!innobase_slow_log_verbose(thd))) return (nullptr);
3324 43810 trx_t *trx = thd_to_trx(thd);
3325
6/6
✓ Branch 0 taken 41975 times.
✓ Branch 1 taken 1835 times.
✓ Branch 2 taken 41877 times.
✓ Branch 3 taken 98 times.
✓ Branch 4 taken 41877 times.
✓ Branch 5 taken 1933 times.
43810 if (trx && UNIV_UNLIKELY(trx->stats.enabled())) return (trx);
3326 1933 return (nullptr);
3327 }
3328
3329 /** InnoDB transaction object that is currently associated with THD is
3330 replaced with that of the 2nd argument. The previous value is
3331 returned through the 3rd argument's buffer, unless it's NULL. When
3332 the buffer is not provided (value NULL) that should mean the caller
3333 restores previously saved association so the current trx has to be
3334 additionally freed from all association with MYSQL.
3335
3336 @param[in,out] thd MySQL thread handle
3337 @param[in] new_trx_arg replacement trx_t
3338 @param[in,out] ptr_trx_arg pointer to a buffer to store old trx_t */
3339 1312 static void innodb_replace_trx_in_thd(THD *thd, void *new_trx_arg,
3340 void **ptr_trx_arg) {
3341
1/2
✓ Branch 0 taken 1312 times.
✗ Branch 1 not taken.
1312 DBUG_TRACE;
3342
1/2
✓ Branch 0 taken 1312 times.
✗ Branch 1 not taken.
1312 trx_t *&trx = thd_to_trx(thd);
3343
3344
5/8
✓ Branch 0 taken 350 times.
✓ Branch 1 taken 962 times.
✓ Branch 2 taken 350 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 350 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1312 times.
1312 ut_ad(new_trx_arg == nullptr || (((trx_t *)new_trx_arg)->mysql_thd == thd &&
3345 !((trx_t *)new_trx_arg)->is_recovered));
3346
3347
2/2
✓ Branch 0 taken 357 times.
✓ Branch 1 taken 955 times.
1312 if (ptr_trx_arg) {
3348 357 *ptr_trx_arg = trx;
3349
3350
5/8
✓ Branch 0 taken 351 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 351 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 351 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 357 times.
357 ut_ad(trx == nullptr || (trx->mysql_thd == thd && !trx->is_recovered));
3351
3352
2/2
✓ Branch 0 taken 672 times.
✓ Branch 1 taken 283 times.
955 } else if (trx != nullptr) {
3353
2/4
✓ Branch 0 taken 672 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 672 times.
672 ut_ad(trx_can_be_handled_by_current_thread_or_is_hp_victim(trx));
3354
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 599 times.
672 if (trx->state.load(std::memory_order_relaxed) == TRX_STATE_NOT_STARTED) {
3355
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
73 ut_ad(thd == trx->mysql_thd);
3356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
73 ut_ad(!trx_is_registered_for_2pc(trx));
3357
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 trx_free_for_mysql(trx);
3358 } else {
3359
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 599 times.
599 ut_ad(thd == trx->mysql_thd);
3360
2/4
✓ Branch 0 taken 599 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 599 times.
599 ut_ad(trx_state_eq(trx, TRX_STATE_PREPARED));
3361 /* The choice not to disconnect transaction when
3362 trx_is_redo_rseg_updated(trx) is false is copied from
3363 the existing detach logic for prepared XA
3364 transactions in innobase_close_connection().
3365 If transaction did not modify anything, rolling it back doesn't modify
3366 the db, but lets us deregister and free the trx object to conserve
3367 resources, while still allowing XA COMMIT it in the future, as it
3368 succeeds on missing xids. */
3369
2/2
✓ Branch 0 taken 591 times.
✓ Branch 1 taken 8 times.
599 if (trx_is_redo_rseg_updated(trx)) {
3370
1/2
✓ Branch 0 taken 591 times.
✗ Branch 1 not taken.
591 trx_disconnect_prepared(trx);
3371 } else {
3372
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 trx_rollback_for_mysql(trx);
3373 8 trx_deregister_from_2pc(trx);
3374
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 trx_free_for_mysql(trx);
3375 }
3376 }
3377 }
3378 1312 trx = static_cast<trx_t *>(new_trx_arg);
3379 1312 }
3380
3381 /** Note that a transaction has been registered with MySQL 2PC coordinator. */
3382 108278428 static inline void trx_register_for_2pc(trx_t *trx) /* in: transaction */
3383 {
3384 108278428 trx->is_registered = true;
3385 108278428 }
3386
3387 21373691 static inline void trx_deregister_from_2pc(trx_t *trx) {
3388 21373691 trx->is_registered = false;
3389 21373691 }
3390
3391 /** Copy table flags from MySQL's HA_CREATE_INFO into an InnoDB table object.
3392 Those flags are stored in .frm file and end up in the MySQL table object,
3393 but are frequently used inside InnoDB so we keep their copies into the
3394 InnoDB table object. */
3395 348251 static void innobase_copy_frm_flags_from_create_info(
3396 dict_table_t *innodb_table, /*!< in/out: InnoDB table */
3397 const HA_CREATE_INFO *create_info) /*!< in: create info */
3398 {
3399 bool ps_on;
3400 bool ps_off;
3401
3402
2/2
✓ Branch 0 taken 153515 times.
✓ Branch 1 taken 194736 times.
348251 if (innodb_table->is_temporary()) {
3403 /* Temp tables do not use persistent stats. */
3404 153515 ps_on = false;
3405 153515 ps_off = true;
3406 } else {
3407 194736 ps_on = create_info->table_options & HA_OPTION_STATS_PERSISTENT;
3408 194736 ps_off = create_info->table_options & HA_OPTION_NO_STATS_PERSISTENT;
3409 }
3410
3411 348251 dict_stats_set_persistent(innodb_table, ps_on, ps_off);
3412
3413 348251 dict_stats_auto_recalc_set(
3414 348251 innodb_table, create_info->stats_auto_recalc == HA_STATS_AUTO_RECALC_ON,
3415 348251 create_info->stats_auto_recalc == HA_STATS_AUTO_RECALC_OFF);
3416
3417 348251 innodb_table->stats_sample_pages = create_info->stats_sample_pages;
3418 348251 }
3419
3420 /** Copy table flags from MySQL's TABLE_SHARE into an InnoDB table object.
3421 Those flags are stored in .frm file and end up in the MySQL table object,
3422 but are frequently used inside InnoDB so we keep their copies into the
3423 InnoDB table object. */
3424 4179730 void innobase_copy_frm_flags_from_table_share(
3425 dict_table_t *innodb_table, /*!< in/out: InnoDB table */
3426 const TABLE_SHARE *table_share) /*!< in: table share */
3427 {
3428 bool ps_on;
3429 bool ps_off;
3430
3431
2/2
✓ Branch 0 taken 273144 times.
✓ Branch 1 taken 3906586 times.
4179730 if (innodb_table->is_temporary()) {
3432 /* Temp tables do not use persistent stats */
3433 273144 ps_on = false;
3434 273144 ps_off = true;
3435 } else {
3436 3906586 ps_on = table_share->db_create_options & HA_OPTION_STATS_PERSISTENT;
3437 3906586 ps_off = table_share->db_create_options & HA_OPTION_NO_STATS_PERSISTENT;
3438 }
3439
3440 4179730 dict_stats_set_persistent(innodb_table, ps_on, ps_off);
3441
3442 4179730 dict_stats_auto_recalc_set(
3443 4179730 innodb_table, table_share->stats_auto_recalc == HA_STATS_AUTO_RECALC_ON,
3444 4179730 table_share->stats_auto_recalc == HA_STATS_AUTO_RECALC_OFF);
3445
3446 4179730 innodb_table->stats_sample_pages = table_share->stats_sample_pages;
3447 4179730 }
3448
3449 850386 int ha_innobase::srv_concurrency_enter() {
3450 850386 auto err = innobase_srv_conc_enter_innodb(m_prebuilt);
3451
3452 850386 trx_t *trx = m_prebuilt->trx;
3453 850386 return convert_error_code_to_mysql(err, 0, trx->mysql_thd);
3454 }
3455
3456 850386 void ha_innobase::srv_concurrency_exit() {
3457 850386 innobase_srv_conc_exit_innodb(m_prebuilt);
3458 850386 }
3459
3460 /** Construct ha_innobase handler. */
3461
3462 9236925 ha_innobase::ha_innobase(handlerton *hton, TABLE_SHARE *table_arg)
3463 : handler(hton, table_arg),
3464 9236930 m_ds_mrr(this),
3465 9236928 m_prebuilt(),
3466 9236928 m_user_thd(),
3467 9236928 m_int_table_flags(
3468 HA_NULL_IN_KEY | HA_CAN_INDEX_BLOBS | HA_CAN_SQL_HANDLER |
3469 HA_PRIMARY_KEY_REQUIRED_FOR_POSITION | HA_PRIMARY_KEY_IN_READ_INDEX |
3470 HA_BINLOG_ROW_CAPABLE | HA_CAN_GEOMETRY | HA_PARTIAL_COLUMN_READ |
3471 HA_TABLE_SCAN_ON_INDEX | HA_CAN_FULLTEXT | HA_CAN_FULLTEXT_EXT |
3472 HA_CAN_FULLTEXT_HINTS | HA_CAN_EXPORT | HA_CAN_RTREEKEYS |
3473 HA_NO_READ_LOCAL_LOCK | HA_GENERATED_COLUMNS |
3474 HA_ATTACHABLE_TRX_COMPATIBLE | HA_CAN_INDEX_VIRTUAL_GENERATED_COLUMN |
3475 HA_DESCENDING_INDEX | HA_MULTI_VALUED_KEY_SUPPORT |
3476 HA_BLOB_PARTIAL_UPDATE | HA_SUPPORTS_GEOGRAPHIC_GEOMETRY_COLUMN |
3477 HA_SUPPORTS_DEFAULT_EXPRESSION | HA_ONLINE_ANALYZE),
3478 9236928 m_start_of_scan(),
3479 9236928 m_stored_select_lock_type(LOCK_NONE_UNSET),
3480 9236925 m_mysql_has_locked() {}
3481
3482 /** Updates the user_thd field in a handle and also allocates a new InnoDB
3483 transaction handle if needed, and updates the transaction fields in the
3484 m_prebuilt struct. */
3485 1175200009 void ha_innobase::update_thd(THD *thd) /*!< in: thd to use the handle */
3486 {
3487
1/2
✓ Branch 0 taken 1175212620 times.
✗ Branch 1 not taken.
1175200009 DBUG_TRACE;
3488
5/8
✓ Branch 0 taken 1175209376 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1175206975 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 69665 times.
✓ Branch 5 taken 1175137310 times.
✓ Branch 6 taken 69665 times.
✗ Branch 7 not taken.
1175212620 DBUG_PRINT("ha_innobase::update_thd",
3489 ("user_thd: %p -> %p", m_user_thd, thd));
3490
3491 /* The table should have been opened in ha_innobase::open(). */
3492
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1175205319 times.
1175206975 assert(m_prebuilt->table->n_ref_count > 0);
3493
3494
1/2
✓ Branch 0 taken 1175211279 times.
✗ Branch 1 not taken.
1175205319 trx_t *trx = check_trx_exists(thd);
3495
3496
1/2
✓ Branch 0 taken 1175205101 times.
✗ Branch 1 not taken.
1175211279 TrxInInnoDB trx_in_innodb(trx);
3497
3498
2/2
✓ Branch 0 taken 24325307 times.
✓ Branch 1 taken 1150879794 times.
1175205101 if (m_prebuilt->trx != trx) {
3499
1/2
✓ Branch 0 taken 24325160 times.
✗ Branch 1 not taken.
24325307 row_update_prebuilt_trx(m_prebuilt, trx);
3500 }
3501
3502 1175204954 m_user_thd = thd;
3503
3504
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1175204954 times.
1175204954 assert(m_prebuilt->trx->magic_n == TRX_MAGIC_N);
3505
2/4
✓ Branch 0 taken 1175205356 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1175205356 times.
1175204954 assert(m_prebuilt->trx == thd_to_trx(m_user_thd));
3506 1175205356 }
3507
3508 /** Updates the user_thd field in a handle and also allocates a new InnoDB
3509 transaction handle if needed, and updates the transaction fields in the
3510 m_prebuilt struct. */
3511
3512 945636823 void ha_innobase::update_thd() {
3513 945636823 THD *thd = ha_thd();
3514
3515
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 945634090 times.
945637888 ut_ad(EQ_CURRENT_THD(thd));
3516 945634090 update_thd(thd);
3517 945640299 }
3518
3519 /** Registers an InnoDB transaction with the MySQL 2PC coordinator, so that
3520 the MySQL XA code knows to call the InnoDB prepare and commit, or rollback
3521 for the transaction. This MUST be called for every transaction for which
3522 the user may call commit or rollback. Calling this several times to register
3523 the same transaction is allowed, too. This function also registers the
3524 current SQL statement. */
3525 108278177 void innobase_register_trx(handlerton *hton, /* in: Innobase handlerton */
3526 THD *thd, /* in: MySQL thd (connection) object */
3527 trx_t *trx) /* in: transaction to register */
3528 {
3529
1/2
✓ Branch 0 taken 108278641 times.
✗ Branch 1 not taken.
108278177 const ulonglong trx_id = static_cast<ulonglong>(trx_get_id_for_print(trx));
3530
3531
1/2
✓ Branch 0 taken 108279439 times.
✗ Branch 1 not taken.
108278641 trans_register_ha(thd, false, hton, &trx_id);
3532
3533
4/4
✓ Branch 0 taken 20676243 times.
✓ Branch 1 taken 87602230 times.
✓ Branch 2 taken 1171050 times.
✓ Branch 3 taken 107107625 times.
128955884 if (!trx_is_registered_for_2pc(trx) &&
3534
3/4
✓ Branch 0 taken 20676445 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1171014 times.
✓ Branch 3 taken 19505431 times.
20676243 thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
3535
1/2
✓ Branch 0 taken 1171246 times.
✗ Branch 1 not taken.
1171050 trans_register_ha(thd, true, hton, &trx_id);
3536 }
3537
3538 108278871 trx_register_for_2pc(trx);
3539 108278763 }
3540
3541 /** Quote a standard SQL identifier like tablespace, index or column name.
3542 @param[in] file output stream
3543 @param[in] trx InnoDB transaction, or NULL
3544 @param[in] id identifier to quote */
3545 1188 void innobase_quote_identifier(FILE *file, trx_t *trx, const char *id) {
3546 const int q =
3547
1/2
✓ Branch 0 taken 1182 times.
✗ Branch 1 not taken.
1182 trx != nullptr && trx->mysql_thd != nullptr
3548
2/2
✓ Branch 0 taken 1182 times.
✓ Branch 1 taken 6 times.
2370 ? get_quote_char_for_identifier(trx->mysql_thd, id, strlen(id))
3549 1188 : '`';
3550
3551
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1188 times.
1188 if (q == EOF) {
3552 fputs(id, file);
3553 } else {
3554 1188 putc(q, file);
3555
3556
2/2
✓ Branch 0 taken 4976 times.
✓ Branch 1 taken 1188 times.
6164 while (int c = *id++) {
3557
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4976 times.
4976 if (c == q) {
3558 putc(c, file);
3559 }
3560 4976 putc(c, file);
3561 4976 }
3562
3563 1188 putc(q, file);
3564 }
3565 1188 }
3566
3567 /** Convert a table name to the MySQL system_charset_info (UTF-8)
3568 and quote it.
3569 @param[out] buf buffer for converted identifier
3570 @param[in] buflen length of buf, in bytes
3571 @param[in] id identifier to convert
3572 @param[in] idlen length of id, in bytes
3573 @param[in] thd MySQL connection thread, or NULL
3574 @return pointer to the end of buf */
3575 26745 static char *innobase_convert_identifier(char *buf, ulint buflen,
3576 const char *id, ulint idlen,
3577 THD *thd) {
3578 26745 const char *s = id;
3579
3580 char nz[MAX_TABLE_NAME_LEN + 1];
3581 char nz2[MAX_TABLE_NAME_LEN + 1];
3582
3583 /* Decode the table name. The MySQL function expects
3584 a NUL-terminated string. The input and output strings
3585 buffers must not be shared. */
3586
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26745 times.
26745 ut_a(idlen <= MAX_TABLE_NAME_LEN);
3587 26745 memcpy(nz, id, idlen);
3588 26745 nz[idlen] = 0;
3589
3590 26745 s = nz2;
3591 idlen =
3592
1/2
✓ Branch 0 taken 26745 times.
✗ Branch 1 not taken.
26745 explain_filename(thd, nz, nz2, sizeof nz2, EXPLAIN_PARTITIONS_AS_COMMENT);
3593
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 26735 times.
26745 if (idlen > buflen) {
3594 10 idlen = buflen;
3595 }
3596 26745 memcpy(buf, s, idlen);
3597 26745 return (buf + idlen);
3598 }
3599
3600 /** Convert a table name to the MySQL system_charset_info (UTF-8).
3601 @return pointer to the end of buf */
3602 13599 char *innobase_convert_name(
3603 char *buf, /*!< out: buffer for converted identifier */
3604 ulint buflen, /*!< in: length of buf, in bytes */
3605 const char *id, /*!< in: table name to convert */
3606 ulint idlen, /*!< in: length of id, in bytes */
3607 THD *thd) /*!< in: MySQL connection thread, or NULL */
3608 {
3609 13599 char *s = buf;
3610 13599 const char *bufend = buf + buflen;
3611
3612 13599 const char *slash = (const char *)memchr(id, '/', idlen);
3613
3614
2/2
✓ Branch 0 taken 446 times.
✓ Branch 1 taken 13153 times.
13599 if (slash == nullptr) {
3615 446 return (innobase_convert_identifier(buf, buflen, id, idlen, thd));
3616 }
3617
3618 /* Print the database name and table name separately. */
3619 13153 s = innobase_convert_identifier(s, bufend - s, id, slash - id, thd);
3620
2/2
✓ Branch 0 taken 13146 times.
✓ Branch 1 taken 7 times.
13153 if (s < bufend) {
3621 13146 *s++ = '.';
3622 13146 s = innobase_convert_identifier(s, bufend - s, slash + 1,
3623 13146 idlen - (slash - id) - 1, thd);
3624 }
3625
3626 13153 return (s);
3627 }
3628
3629 /** A wrapper function of innobase_convert_name(), convert a table name
3630 to the MySQL system_charset_info (UTF-8) and quote it if needed.
3631 @param[out] buf Buffer for converted identifier
3632 @param[in] buflen Length of buf, in bytes
3633 @param[in] name Table name to format */
3634 147 void innobase_format_name(char *buf, ulint buflen, const char *name) {
3635 const char *bufend;
3636
3637 147 bufend = innobase_convert_name(buf, buflen, name, strlen(name), nullptr);
3638
3639
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 147 times.
147 ut_ad((ulint)(bufend - buf) < buflen);
3640
3641 147 buf[bufend - buf] = '\0';
3642 147 }
3643
3644 /** Determines if the currently running transaction has been interrupted.
3645 @return true if interrupted */
3646 457133775 bool trx_is_interrupted(const trx_t *trx) /*!< in: transaction */
3647 {
3648
6/6
✓ Branch 0 taken 457004672 times.
✓ Branch 1 taken 129103 times.
✓ Branch 2 taken 457004583 times.
✓ Branch 3 taken 89 times.
✓ Branch 4 taken 77 times.
✓ Branch 5 taken 457004380 times.
457133775 return (trx && trx->mysql_thd && thd_killed(trx->mysql_thd));
3649 }
3650
3651 /** Determines if the currently running transaction is in strict mode.
3652 @return true if strict */
3653 374251 bool trx_is_strict(trx_t *trx) /*!< in: transaction */
3654 {
3655 /* Relax strict check if table is in truncate create table */
3656
4/6
✓ Branch 0 taken 374251 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 374251 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 370628 times.
✓ Branch 5 taken 3623 times.
744879 return (trx && trx->mysql_thd && THDVAR(trx->mysql_thd, strict_mode) &&
3657
2/2
✓ Branch 0 taken 338794 times.
✓ Branch 1 taken 31834 times.
744879 (!trx->in_truncate));
3658 }
3659
3660 #ifdef WITH_WSREP
3661 /** Determines if the currently running transaction is a wsrep transaction.
3662 @return true if transaction is a wsrep transaction */
3663 1943 bool trx_is_wsrep_trx(const trx_t *trx) /*!< in: transaction */
3664 {
3665
3/4
✓ Branch 0 taken 1943 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 375 times.
✓ Branch 3 taken 1568 times.
1943 return (trx && wsrep_on(trx->mysql_thd));
3666 }
3667 #endif /* WITH_WSREP */
3668
3669 /** Resets some fields of a m_prebuilt struct. The template is used in fast
3670 retrieval of just those column values MySQL needs in its processing. */
3671 421652864 void ha_innobase::reset_template(void) {
3672
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 421654788 times.
421652864 ut_ad(m_prebuilt->magic_n == ROW_PREBUILT_ALLOCATED);
3673
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 421655317 times.
421654788 ut_ad(m_prebuilt->magic_n2 == m_prebuilt->magic_n);
3674
3675 /* Force table to be freed in close_thread_table(). */
3676
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 421655347 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
421655317 DBUG_EXECUTE_IF(
3677 "free_table_in_fts_query",
3678 if (m_prebuilt->in_fts_query) { table->invalidate_dict(); });
3679
3680 421655347 m_prebuilt->keep_other_fields_on_keyread = 0;
3681 421655347 m_prebuilt->read_just_key = 0;
3682 421655347 m_prebuilt->in_fts_query = false;
3683 421655347 m_prebuilt->m_end_range = false;
3684
3685 /* Reset index condition pushdown state. */
3686
2/2
✓ Branch 0 taken 2431 times.
✓ Branch 1 taken 421652916 times.
421655347 if (m_prebuilt->idx_cond) {
3687 2431 m_prebuilt->idx_cond = false;
3688 2431 m_prebuilt->idx_cond_n_cols = 0;
3689 /* Invalidate m_prebuilt->mysql_template
3690 in ha_innobase::write_row(). */
3691 2431 m_prebuilt->template_type = ROW_MYSQL_NO_TEMPLATE;
3692 }
3693 421655347 }
3694
3695 /** Call this when you have opened a new table handle in HANDLER, before you
3696 call index_read_map() etc. Actually, we can let the cursor stay open even
3697 over a transaction commit! Then you should call this before every operation,
3698 fetch next etc. This function inits the necessary things even after a
3699 transaction commit. */
3700
3701 74184 void ha_innobase::init_table_handle_for_HANDLER(void) {
3702 /* If current thd does not yet have a trx struct, create one.
3703 If the current handle does not yet have a m_prebuilt struct, create
3704 one. Update the trx pointers in the m_prebuilt struct. Normally
3705 this operation is done in external_lock. */
3706
3707
2/4
✓ Branch 0 taken 74184 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 74184 times.
✗ Branch 3 not taken.
74184 update_thd(ha_thd());
3708
3709 /* Initialize the m_prebuilt struct much like it would be inited in
3710 external_lock */
3711
3712
1/2
✓ Branch 0 taken 74184 times.
✗ Branch 1 not taken.
74184 innobase_srv_conc_force_exit_innodb(m_prebuilt->trx);
3713
3714 /* If the transaction is not started yet, start it */
3715
3716
1/2
✓ Branch 0 taken 74184 times.
✗ Branch 1 not taken.
74184 trx_start_if_not_started_xa(m_prebuilt->trx, false, UT_LOCATION_HERE);
3717
3718
1/2
✓ Branch 0 taken 74184 times.
✗ Branch 1 not taken.
74184 TrxInInnoDB trx_in_innodb(m_prebuilt->trx);
3719
3720 /* Assign a read view if the transaction does not have it yet */
3721
3722
1/2
✓ Branch 0 taken 74184 times.
✗ Branch 1 not taken.
74184 trx_assign_read_view(m_prebuilt->trx);
3723
3724
1/2
✓ Branch 0 taken 74184 times.
✗ Branch 1 not taken.
74184 innobase_register_trx(ht, m_user_thd, m_prebuilt->trx);
3725
3726 /* We did the necessary inits in this function, no need to repeat them
3727 in row_search_for_mysql */
3728
3729 74184 m_prebuilt->sql_stat_start = false;
3730
3731 /* We let HANDLER always to do the reads as consistent reads, even
3732 if the trx isolation level would have been specified as SERIALIZABLE */
3733
3734 74184 m_prebuilt->select_lock_type = LOCK_NONE;
3735 74184 m_prebuilt->select_mode = SELECT_ORDINARY;
3736 74184 m_stored_select_lock_type = LOCK_NONE;
3737
3738 /* Always fetch all columns in the index record */
3739
3740 74184 m_prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS;
3741
3742 /* We want always to fetch all columns in the whole row? Or do
3743 we???? */
3744
3745 74184 m_prebuilt->used_in_HANDLER = true;
3746
3747
1/2
✓ Branch 0 taken 74184 times.
✗ Branch 1 not taken.
74184 reset_template();
3748 74184 }
3749
3750 /** Free any resources that were allocated and return failure.
3751 @return always return 1 */
3752 101 static int innodb_init_abort() {
3753
1/2
✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
101 DBUG_TRACE;
3754
1/2
✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
101 srv_shutdown_exit_threads();
3755
1/2
✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
101 innodb_space_shutdown();
3756
1/2
✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
101 innobase::component_services::deinitialize_service_handles();
3757
1/2
✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
101 release_plugin_services();
3758 101 return 1;
3759 101 }
3760
3761 /** Open or create InnoDB data files.
3762 @param[in] dict_init_mode whether to create or open the files
3763 @param[in,out] tablespaces predefined tablespaces created by the DDSE
3764 @return 0 on success, 1 on failure */
3765 [[nodiscard]] static int innobase_init_files(
3766 dict_init_mode_t dict_init_mode,
3767 List<const Plugin_tablespace> *tablespaces,
3768 bool &is_dd_encrypted);
3769
3770 /** Initialize InnoDB for being used to store the DD tables.
3771 Create the required files according to the dict_init_mode.
3772 Create strings representing the required DDSE tables, i.e.,
3773 tables that InnoDB expects to exist in the DD,
3774 and add them to the appropriate out parameter.
3775
3776 @param[in] dict_init_mode How to initialize files
3777
3778 @param[in] version Target DD version if a new server
3779 is being installed.
3780 0 if restarting an existing server.
3781
3782 @param[out] tables List of SQL DDL statements
3783 for creating DD tables that
3784 are needed by the DDSE.
3785
3786 @param[out] tablespaces List of meta data for predefined
3787 tablespaces created by the DDSE.
3788
3789 @retval true An error occurred.
3790 @retval false Success - no errors. */
3791 static bool innobase_ddse_dict_init(dict_init_mode_t dict_init_mode,
3792 uint version,
3793 List<const dd::Object_table> *tables,
3794 List<const Plugin_tablespace> *tablespaces);
3795
3796 /** Save the state of undo tablespaces from the dd to the undo::Tablespace
3797 @param[in] space_id tablespace ID
3798 @param[in] dd_space dd::Tablespace object
3799 @return true if success and false if the undo tablespace state is not saved. */
3800 18913 bool apply_dd_undo_state(space_id_t space_id, const dd::Tablespace *dd_space) {
3801 18913 bool success = true;
3802
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18913 times.
18913 if (!fsp_is_undo_tablespace(space_id)) {
3803 return (success);
3804 }
3805
3806 /* Get the state of undo tablespaces from the DD. */
3807 18913 dd_space_states state = dd_tablespace_get_state_enum(dd_space, space_id);
3808
3809 18913 undo::spaces->s_lock();
3810
3811 18913 space_id_t space_num = undo::id2num(space_id);
3812 18913 undo::Tablespace *undo_space = undo::spaces->find(space_num);
3813
3814
3/5
✓ Branch 0 taken 18851 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 60 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
18913 switch (state) {
3815 18851 case DD_SPACE_STATE__LAST:
3816 /* If the "state" key is missing the DD might have been built with
3817 an older version. */
3818 case DD_SPACE_STATE_ACTIVE:
3819 /* Explicit undo spaces with no undo logs are set empty during
3820 startup to avoid getting undo. */
3821
2/2
✓ Branch 0 taken 203 times.
✓ Branch 1 taken 18648 times.
18851 if (undo_space->is_empty()) {
3822 203 undo_space->set_active();
3823 }
3824
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18851 times.
18851 ut_ad(undo_space->is_active());
3825 18851 break;
3826 2 case DD_SPACE_STATE_INACTIVE:
3827 2 undo_space->set_inactive_explicit();
3828 2 srv_wake_purge_thread_if_not_active();
3829
3830 2 break;
3831 60 case DD_SPACE_STATE_EMPTY:
3832 60 undo_space->set_empty();
3833 60 break;
3834 case DD_SPACE_STATE_NORMAL:
3835 case DD_SPACE_STATE_DISCARDED:
3836 case DD_SPACE_STATE_CORRUPTED:
3837 success = false;
3838 break;
3839 }
3840
3841 18913 undo::spaces->s_unlock();
3842
3843 18913 return (success);
3844 }
3845
3846 /** Initialize the set of hard coded DD table ids.
3847 @param[in] dd_table_id Table id of DD table. */
3848 static void innobase_dict_register_dd_table_id(dd::Object_id dd_table_id);
3849
3850 /** Validate the DD tablespace data against what's read during the
3851 directory scan on startup. */
3852 class Validate_files {
3853 using DD_tablespaces = std::vector<const dd::Tablespace *>;
3854 using Const_iter = DD_tablespaces::const_iterator;
3855
3856 public:
3857 /** Constructor */
3858 9331 Validate_files()
3859 9331 : m_mutex(),
3860 9331 m_space_max_id(),
3861 9331 m_n_to_check(),
3862 9331 m_n_threads(),
3863 9331 m_start_time(std::chrono::steady_clock::time_point{}),
3864 9331 m_n_validated(),
3865 9331 m_n_skipped(),
3866 9331 m_n_moved(),
3867 9331 m_n_missing(),
3868 9331 m_n_deleted(),
3869 9331 m_n_errors() {}
3870
3871 /** Validate the discovered tablespaces against the DD and attempt to open
3872 any DD tablespace not already open using a Parallel For Loop (par_for).
3873 @param[in] tablespaces Tablespace files read from the DD
3874 @return DB_SUCCESS if all OK */
3875 [[nodiscard]] dberr_t validate(const DD_tablespaces &tablespaces);
3876
3877 private:
3878 /** Validate a range of tablespaces from the DD.
3879 1. Compare the discovered files against those known to the dictionary.
3880 2. Open any tablespace known to the DD but not discovered and opened
3881 from the known directories.
3882 3. Update the DD if a tablespace has moved.
3883 4. Update the DD if an undo tablespace was truncated and replaced.
3884 5. If innodb_validate_tablespace_paths is set and this is not called
3885 while in recovery, only validate undo tablespaces.
3886 6. Track the number of skipped, moved, missing and deleted tablespaces.
3887 7. Return failure for any unexpected error.
3888 @param[in] begin Start of the slice
3889 @param[in] end End of the slice
3890 @param[in] thread_id Thread ID */
3891 void check(const Const_iter &begin, const Const_iter &end, size_t thread_id);
3892
3893 /** @return true if there were failures. */
3894 18662 bool failed() const { return (m_n_errors.load() != 0); }
3895
3896 /** @return the maximum tablespace ID found. */
3897 9331 space_id_t get_space_max_id() const { return (m_space_max_id); }
3898
3899 private:
3900 /** Mutex protecting the parallel check. */
3901 std::mutex m_mutex;
3902
3903 /** Maximum tablespace ID found. */
3904 space_id_t m_space_max_id;
3905
3906 /** Number of tablespaces to check. */
3907 size_t m_n_to_check;
3908
3909 /** Number of threads used in the parallel for. */
3910 size_t m_n_threads;
3911
3912 /** The time when Validate_files::validate() starts or the last time
3913 one of the threads reported progress. */
3914 std::atomic<std::chrono::steady_clock::time_point> m_start_time;
3915 static_assert(decltype(m_start_time)::is_always_lock_free);
3916
3917 /** Number of tablespaces validated. */
3918 std::atomic_size_t m_n_validated;
3919
3920 /** Number of tablespaces skipped. */
3921 std::atomic_size_t m_n_skipped;
3922
3923 /** Number of tablespaces moved. */
3924 std::atomic_size_t m_n_moved;
3925
3926 /** Number of tablespaces missing. */
3927 std::atomic_size_t m_n_missing;
3928
3929 /** Number of tablespaces deleted. */
3930 std::atomic_size_t m_n_deleted;
3931
3932 /** Number of threads that failed. */
3933 std::atomic_size_t m_n_errors;
3934 };
3935
3936 9331 void Validate_files::check(const Const_iter &begin, const Const_iter &end,
3937 size_t thread_id) {
3938 9331 const auto sys_space_name = dict_sys_t::s_sys_space_name;
3939
3940
1/2
✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
9331 auto heap = mem_heap_create(FN_REFLEN * 2 + 1, UT_LOCATION_HERE);
3941
3942 /* If the setting for innodb_validate_tablespace_paths is NO and we are
3943 not in recovery, then only validate undo tablespaces. */
3944 9331 const bool ibd_validate =
3945
4/4
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 9320 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 9 times.
9331 srv_validate_tablespace_paths || recv_needed_recovery;
3946
3947 9331 std::string prefix;
3948
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9331 times.
9331 if (m_n_threads > 0) {
3949 std::ostringstream msg;
3950 msg << "Thread# " << thread_id << " - ";
3951 prefix = msg.str();
3952 }
3953
3954
2/2
✓ Branch 0 taken 91262 times.
✓ Branch 1 taken 9331 times.
100593 for (auto it = begin; it != end; ++it) {
3955 91262 const auto &dd_tablespace = *it;
3956
3957
3/6
✓ Branch 0 taken 91262 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91262 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 91262 times.
91262 if (std::chrono::steady_clock::now() - m_start_time.load() >=
3958 PRINT_INTERVAL) {
3959 m_start_time = std::chrono::steady_clock::now();
3960
3961 std::ostringstream msg;
3962
3963 if (m_n_threads) {
3964 msg << m_n_threads << "threads have validated ";
3965 } else {
3966 msg << "Validated ";
3967 }
3968
3969 msg << m_n_validated << " out of " << m_n_to_check
3970 << " tablespaces so far.";
3971
3972 if (m_n_skipped > 0) {
3973 msg << " Skipped=" << m_n_skipped << ".";
3974 }
3975 if (m_n_moved > 0) {
3976 msg << " Moved=" << m_n_moved << ".";
3977 }
3978 if (m_n_missing > 0) {
3979 msg << " Missing=" << m_n_missing << ".";
3980 }
3981 if (m_n_deleted > 0) {
3982 msg << " Deleted=" << m_n_deleted << ".";
3983 }
3984
3985 ib::info(ER_IB_MSG_525) << msg.str();
3986 }
3987
3988
3/6
✓ Branch 0 taken 91262 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91262 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 91262 times.
91262 if (dd_tablespace->engine() != innobase_hton_name) {
3989 ++m_n_skipped;
3990 50494 continue;
3991 }
3992
3993 91262 bool is_enc_in_progress{false};
3994
1/2
✓ Branch 0 taken 91262 times.
✗ Branch 1 not taken.
91262 const auto &p = dd_tablespace->se_private_data();
3995
1/2
✓ Branch 0 taken 91262 times.
✗ Branch 1 not taken.
91262 const auto &o = dd_tablespace->options();
3996
1/2
✓ Branch 0 taken 91262 times.
✗ Branch 1 not taken.
91262 const char *space_name = dd_tablespace->name().c_str();
3997 91262 const auto se_key_value = dd_space_key_strings;
3998
3999 /* There should be exactly one file name associated
4000 with each InnoDB tablespace, except innodb_system */
4001
4002 space_id_t space_id;
4003
3/6
✓ Branch 0 taken 91262 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91262 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 91262 times.
91262 if (p.get(se_key_value[DD_SPACE_ID], &space_id)) {
4004 /* Failed to fetch the tablespace ID */
4005 ++m_n_errors;
4006 break;
4007 }
4008
4009 /* If --innodb_validate_tablespace_paths=OFF and
4010 startup is not in recovery, then skip all IBD files. */
4011
7/8
✓ Branch 0 taken 155 times.
✓ Branch 1 taken 91107 times.
✓ Branch 2 taken 155 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 137 times.
✓ Branch 5 taken 18 times.
✓ Branch 6 taken 137 times.
✓ Branch 7 taken 91125 times.
91262 if (!ibd_validate && !fsp_is_undo_tablespace(space_id)) {
4012 137 ++m_n_skipped;
4013 137 continue;
4014 }
4015
4016 /* Do not open a discovered tablespace that is currently discarded.
4017 It will be opened properly when it is imported. */
4018
1/2
✓ Branch 0 taken 91125 times.
✗ Branch 1 not taken.
91125 dd_space_states dd_state = dd_tablespace_get_state_enum(&p, space_id);
4019
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 91065 times.
91125 if (dd_state == DD_SPACE_STATE_DISCARDED) {
4020 60 ++m_n_skipped;
4021 60 continue;
4022 }
4023
4024
5/10
✓ Branch 0 taken 91065 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91065 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 91064 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 91065 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
182131 if (p.exists(se_key_value[DD_SPACE_ONLINE_ENC_PROGRESS]) &&
4025
6/12
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 91064 times.
✓ Branch 8 taken 91065 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
91066 p.get(se_key_value[DD_SPACE_ONLINE_ENC_PROGRESS],
4026 &is_enc_in_progress)) {
4027 ++m_n_errors;
4028 break;
4029 }
4030
4031 /* Get the spacename for this tablespace from the DD. */
4032
4/6
✓ Branch 0 taken 91065 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 91045 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 91065 times.
91085 if (dd_tablespace->files().size() != 1 &&
4033
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 strcmp(space_name, sys_space_name) != 0) {
4034 /* Only the InnoDB system tablespace has support for
4035 multiple files per tablespace. For historial reasons. */
4036 ++m_n_errors;
4037 break;
4038 }
4039
4040 {
4041
1/2
✓ Branch 0 taken 91065 times.
✗ Branch 1 not taken.
91065 std::lock_guard<std::mutex> guard(m_mutex);
4042
4043
6/6
✓ Branch 0 taken 53493 times.
✓ Branch 1 taken 37572 times.
✓ Branch 2 taken 44012 times.
✓ Branch 3 taken 9481 times.
✓ Branch 4 taken 44012 times.
✓ Branch 5 taken 47053 times.
91065 if (!dict_sys_t::is_reserved(space_id) && space_id > m_space_max_id) {
4044 /* Currently try to find the max space_id only.
4045 It should be able to reuse the deleted smaller ones later */
4046 44012 m_space_max_id = space_id;
4047 }
4048 91065 }
4049
4050 /* System and temp files are tracked and opened separately.
4051 Consider them validated. */
4052
3/4
✓ Branch 0 taken 91065 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18644 times.
✓ Branch 3 taken 72421 times.
91065 if (fsp_is_system_or_temp_tablespace(space_id)) {
4053 18644 ++m_n_validated;
4054 18644 continue;
4055 }
4056
4057 /* Get the filename for this tablespace from the DD. */
4058
3/6
✓ Branch 0 taken 72421 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 72421 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 72421 times.
✗ Branch 5 not taken.
72421 const auto file = *dd_tablespace->files().begin();
4059
2/4
✓ Branch 0 taken 72421 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 72421 times.
✗ Branch 3 not taken.
72421 std::string dd_path{file->filename().c_str()};
4060 72421 const char *filename = dd_path.c_str();
4061
4062 /* If the trunc log file is still around, this undo tablespace needs to be
4063 rebuilt now. */
4064
3/4
✓ Branch 0 taken 72421 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18928 times.
✓ Branch 3 taken 53493 times.
72421 if (fsp_is_undo_tablespace(space_id)) {
4065
1/2
✓ Branch 0 taken 18928 times.
✗ Branch 1 not taken.
18928 mutex_enter(&undo::ddl_mutex);
4066
1/2
✓ Branch 0 taken 18928 times.
✗ Branch 1 not taken.
18928 dberr_t err = srv_undo_tablespace_fixup(space_name, filename, space_id);
4067
1/2
✓ Branch 0 taken 18928 times.
✗ Branch 1 not taken.
18928 mutex_exit(&undo::ddl_mutex);
4068
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18928 times.
18928 if (err != DB_SUCCESS) {
4069 ib::error(ER_IB_MSG_FAILED_TO_FINISH_TRUNCATE, prefix.c_str(),
4070 space_name);
4071 continue;
4072 }
4073 }
4074
4075 /* Check if IBD tablespaces exist in mem correctly. This call also adjusts
4076 the tablespace name for undo and general tablespace. We still need to check
4077 if the data files are moved. */
4078
3/4
✓ Branch 0 taken 72421 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31403 times.
✓ Branch 3 taken 41018 times.
72421 if (fil_space_exists_in_mem(space_id, space_name, false, true)) {
4079
4/6
✓ Branch 0 taken 31403 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18913 times.
✓ Branch 3 taken 12490 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 31403 times.
50316 if (fsp_is_undo_tablespace(space_id) &&
4080
2/4
✓ Branch 0 taken 18913 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18913 times.
18913 !apply_dd_undo_state(space_id, dd_tablespace)) {
4081 /* Undo tablespaces are always opened first. But in case they have
4082 been moved and the DD needs to be updated, we fall thru to the location
4083 check below. First though, update the DD tablespace state. */
4084 ib::warn(ER_IB_MSG_FAIL_TO_SAVE_SPACE_STATE, prefix.c_str(),
4085 space_name);
4086 }
4087 }
4088
4089 /* Check the file paths of IBD and Undo datafiles below. */
4090
6/10
✓ Branch 0 taken 72421 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18928 times.
✓ Branch 3 taken 53493 times.
✓ Branch 4 taken 18928 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 18928 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 72421 times.
72421 if (!fsp_is_ibd_tablespace(space_id) && !fsp_is_undo_tablespace(space_id)) {
4091 continue;
4092 }
4093
4094 /* Check if any IBD or Undo files are moved, deleted or missing. */
4095 72421 std::string new_path;
4096
4097 /* Just in case this dictionary was ported between
4098 Windows and POSIX. */
4099 72421 Fil_path::normalize(dd_path);
4100 72421 Fil_state state = Fil_state::MATCHES;
4101
4102 72421 uint32_t fsp_flags = 0;
4103
3/6
✓ Branch 0 taken 72421 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 72421 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 72421 times.
72421 if (p.get(se_key_value[DD_SPACE_FLAGS], &fsp_flags)) {
4104 /* Failed to fetch the tablespace flags. */
4105 ++m_n_errors;
4106 break;
4107 }
4108
4109
1/2
✓ Branch 0 taken 72421 times.
✗ Branch 1 not taken.
72421 std::lock_guard<std::mutex> guard(m_mutex);
4110
4111
2/4
✓ Branch 0 taken 72421 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 72421 times.
✗ Branch 3 not taken.
72421 state = fil_tablespace_path_equals(space_id, space_name, fsp_flags, dd_path,
4112 &new_path);
4113
4114
2/2
✓ Branch 0 taken 72111 times.
✓ Branch 1 taken 310 times.
72421 if (state == Fil_state::MATCHES) {
4115
1/2
✓ Branch 0 taken 72111 times.
✗ Branch 1 not taken.
72111 new_path.assign(dd_path);
4116 }
4117
4118
1/2
✓ Branch 0 taken 72421 times.
✗ Branch 1 not taken.
72421 std::string space_str(space_name);
4119
4120 72421 std::string old_space;
4121 72421 bool file_name_changed = false;
4122 72421 bool file_path_changed = (state == Fil_state::MOVED);
4123
4124
4/4
✓ Branch 0 taken 310 times.
✓ Branch 1 taken 72111 times.
✓ Branch 2 taken 91 times.
✓ Branch 3 taken 219 times.
72421 if (state == Fil_state::MATCHES || state == Fil_state::MOVED) {
4125 /* We need to update space name and table name for partitioned tables
4126 if letter case is different. */
4127
3/4
✓ Branch 0 taken 72202 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 109 times.
✓ Branch 3 taken 72093 times.
72202 if (fil_update_partition_name(space_id, fsp_flags, true, space_str,
4128 new_path)) {
4129 109 file_name_changed = true;
4130 109 state = Fil_state::MOVED;
4131 }
4132
4133 /* Update DD if tablespace name is corrected. */
4134
2/2
✓ Branch 0 taken 153 times.
✓ Branch 1 taken 72049 times.
72202 if (space_str.compare(space_name) != 0) {
4135
1/2
✓ Branch 0 taken 153 times.
✗ Branch 1 not taken.
153 old_space.assign(space_name);
4136 153 space_name = space_str.c_str();
4137 153 state = Fil_state::MOVED;
4138 }
4139 }
4140
4141
3/6
✓ Branch 0 taken 71976 times.
✓ Branch 1 taken 219 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 226 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
72421 switch (state) {
4142 71976 case Fil_state::MATCHES:
4143 71976 break;
4144
4145 219 case Fil_state::MISSING:
4146
4147
5/10
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 219 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 219 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 219 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 219 times.
✗ Branch 9 not taken.
438 ib::warn(ER_IB_MSG_526) << prefix << "Tablespace " << space_id << ","
4148
3/6
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 219 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 219 times.
✗ Branch 5 not taken.
219 << " name '" << space_name << "',"
4149
3/6
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 219 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 219 times.
✗ Branch 5 not taken.
219 << " file '" << dd_path << "'"
4150
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 << " is missing!";
4151
4152
3/4
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 217 times.
219 if (fsp_is_undo_tablespace(space_id)) {
4153 /* This deserves a special error message. */
4154
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 ib::error(ER_IB_MSG_CANNOT_FIND_DD_UNDO_SPACE, space_name, filename);
4155 }
4156 219 ++m_n_missing;
4157 219 continue;
4158
4159 case Fil_state::DELETED:
4160
4161 ib::warn(ER_IB_MSG_527) << prefix << "Tablespace " << space_id << ","
4162 << " name '" << space_name << "',"
4163 << " file '" << dd_path << "'"
4164 << " was deleted!";
4165 ++m_n_deleted;
4166 continue;
4167
4168 226 case Fil_state::MOVED:
4169
2/4
✓ Branch 0 taken 226 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 226 times.
✗ Branch 3 not taken.
226 fil_add_moved_space(dd_tablespace->id(), space_id, space_name, dd_path,
4170 new_path);
4171 226 ++m_n_moved;
4172
4173
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 226 times.
226 if (m_n_moved > MOVED_FILES_PRINT_THRESHOLD) {
4174 filename = new_path.c_str();
4175
4176 break;
4177 }
4178
4179
2/2
✓ Branch 0 taken 153 times.
✓ Branch 1 taken 73 times.
226 if (!old_space.empty()) {
4180
1/2
✓ Branch 0 taken 153 times.
✗ Branch 1 not taken.
153 ib::info(ER_IB_MSG_FIL_STATE_MOVED_CORRECTED, prefix.c_str(),
4181 153 static_cast<unsigned long long>(dd_tablespace->id()),
4182
1/2
✓ Branch 0 taken 153 times.
✗ Branch 1 not taken.
306 static_cast<unsigned int>(space_id), old_space.c_str(),
4183 space_name);
4184 }
4185
4186
2/2
✓ Branch 0 taken 91 times.
✓ Branch 1 taken 135 times.
226 if (file_path_changed) {
4187
1/2
✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
91 ib::info(ER_IB_MSG_FIL_STATE_MOVED_CHANGED_PATH, prefix.c_str(),
4188 91 static_cast<unsigned long long>(dd_tablespace->id()),
4189 static_cast<unsigned int>(space_id), space_name,
4190
1/2
✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
182 dd_path.c_str(), new_path.c_str());
4191
4192
2/2
✓ Branch 0 taken 109 times.
✓ Branch 1 taken 26 times.
135 } else if (file_name_changed) {
4193
1/2
✓ Branch 0 taken 109 times.
✗ Branch 1 not taken.
109 ib::info(ER_IB_MSG_FIL_STATE_MOVED_CHANGED_NAME, prefix.c_str(),
4194 109 static_cast<unsigned long long>(dd_tablespace->id()),
4195 static_cast<unsigned int>(space_id), space_name,
4196
1/2
✓ Branch 0 taken 109 times.
✗ Branch 1 not taken.
218 dd_path.c_str(), new_path.c_str());
4197 }
4198
4199 226 filename = new_path.c_str();
4200
4201
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 226 times.
226 if (m_n_moved == MOVED_FILES_PRINT_THRESHOLD) {
4202 ib::info(ER_IB_MSG_FIL_STATE_MOVED_TOO_MANY, prefix.c_str());
4203 }
4204 226 break;
4205
4206 case Fil_state::RENAMED:
4207 break;
4208 }
4209
4210 /* If this space is already open, we can move on to the next. */
4211
3/4
✓ Branch 0 taken 72202 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31421 times.
✓ Branch 3 taken 40781 times.
72202 if (nullptr != fil_space_get(space_id)) {
4212 /* Set the autoextend_size attribute for the newly opened space. */
4213 31421 uint64_t autoextend_size{};
4214
4215
6/10
✓ Branch 0 taken 31421 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31421 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 21693 times.
✓ Branch 5 taken 9728 times.
✓ Branch 6 taken 21693 times.
✓ Branch 7 taken 9728 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
84535 if (o.exists(autoextend_size_str) &&
4216
6/12
✓ Branch 0 taken 21693 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21693 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 21693 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 21693 times.
✓ Branch 7 taken 9728 times.
✓ Branch 8 taken 31421 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
53114 !o.get(autoextend_size_str, &autoextend_size)) {
4217
1/2
✓ Branch 0 taken 21693 times.
✗ Branch 1 not taken.
21693 ut_d(dberr_t ret =) fil_set_autoextend_size(space_id, autoextend_size);
4218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21693 times.
21693 ut_ad(ret == DB_SUCCESS);
4219 }
4220 31421 ++m_n_validated;
4221 31421 continue;
4222 31421 }
4223
4224
3/4
✓ Branch 0 taken 40781 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 40768 times.
40781 if (fsp_is_undo_tablespace(space_id)) {
4225 /* The undo space may be open with a alternate space_id */
4226 13 space_id_t space_num = undo::id2num(space_id);
4227
3/4
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 1 times.
13 if (nullptr != undo::spaces->find(space_num)) {
4228 12 ++m_n_validated;
4229 12 continue;
4230 }
4231
4232 /* If an undo tablespace from the DD is in an unknown location,
4233 it will not yet be open. */
4234 1 undo::Tablespace undo_space(space_id);
4235
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 undo_space.set_space_name(space_name);
4236
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 undo_space.set_file_name(filename);
4237
4238
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 mutex_enter(&undo::ddl_mutex);
4239
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 undo::spaces->x_lock();
4240
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 undo::use_space_id(space_id);
4241
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 dberr_t err = srv_undo_tablespace_open(undo_space);
4242
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 undo::spaces->x_unlock();
4243
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 mutex_exit(&undo::ddl_mutex);
4244
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (err != DB_SUCCESS) {
4245 ib::error(ER_IB_MSG_CANNOT_FIND_DD_UNDO_SPACE, space_name, filename);
4246 }
4247 1 ++m_n_validated;
4248 1 continue;
4249 1 }
4250
4251 40768 Keyring_encryption_info keyring_encryption_info;
4252
4253 /* It's safe to pass space_name in tablename charset because
4254 filename is already in filename charset. */
4255
4/4
✓ Branch 0 taken 10613 times.
✓ Branch 1 taken 30155 times.
✓ Branch 2 taken 10602 times.
✓ Branch 3 taken 11 times.
40768 bool validate = recv_needed_recovery && srv_force_recovery == 0;
4256 dberr_t err =
4257
4/6
✓ Branch 0 taken 30166 times.
✓ Branch 1 taken 10602 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 30166 times.
✓ Branch 4 taken 40768 times.
✗ Branch 5 not taken.
40768 fil_ibd_open(validate || is_enc_in_progress, FIL_TYPE_TABLESPACE,
4258 space_id, fsp_flags, space_name, filename, false,
4259 false, keyring_encryption_info);
4260
4261
2/2
✓ Branch 0 taken 40699 times.
✓ Branch 1 taken 69 times.
40768 switch (err) {
4262 40699 case DB_SUCCESS: {
4263 /* Set the autoextend_size attribute for the newly opened space. */
4264 40699 uint64_t autoextend_size{};
4265
4266
6/10
✓ Branch 0 taken 40699 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40699 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 39822 times.
✓ Branch 5 taken 877 times.
✓ Branch 6 taken 39822 times.
✓ Branch 7 taken 877 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
121220 if (o.exists(autoextend_size_str) &&
4267
6/12
✓ Branch 0 taken 39822 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39822 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 39822 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 39822 times.
✓ Branch 7 taken 877 times.
✓ Branch 8 taken 40699 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
80521 !o.get(autoextend_size_str, &autoextend_size)) {
4268 ut_d(dberr_t ret =)
4269
1/2
✓ Branch 0 taken 39822 times.
✗ Branch 1 not taken.
39822 fil_set_autoextend_size(space_id, autoextend_size);
4270
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39822 times.
39822 ut_ad(ret == DB_SUCCESS);
4271 }
4272 40699 ++m_n_validated;
4273 40699 break;
4274 }
4275 69 case DB_CANNOT_OPEN_FILE:
4276 case DB_WRONG_FILE_NAME:
4277 default:
4278
5/10
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 69 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 69 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 69 times.
✗ Branch 9 not taken.
69 ib::info(ER_IB_MSG_530) << prefix << "Tablespace " << space_id << ","
4279
3/6
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 69 times.
✗ Branch 5 not taken.
69 << " name '" << space_name << "',"
4280
1/2
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
69 << " unable to open file"
4281
5/10
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 69 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 69 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 69 times.
✗ Branch 9 not taken.
69 << " '" << filename << "' - " << ut_strerr(err);
4282 69 ++m_n_missing;
4283 }
4284
10/12
✓ Branch 0 taken 40768 times.
✓ Branch 1 taken 31653 times.
✓ Branch 2 taken 40768 times.
✓ Branch 3 taken 31653 times.
✓ Branch 4 taken 40768 times.
✓ Branch 5 taken 31653 times.
✓ Branch 6 taken 40768 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 31653 times.
✓ Branch 9 taken 40768 times.
✓ Branch 10 taken 31653 times.
✗ Branch 11 not taken.
199033 }
4285
4286
1/2
✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
9331 mem_heap_free(heap);
4287 9331 }
4288
4289 9331 dberr_t Validate_files::validate(const DD_tablespaces &tablespaces) {
4290 9331 m_n_to_check = tablespaces.size();
4291
1/2
✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
9331 m_n_threads = fil_get_scan_threads(m_n_to_check);
4292 9331 m_start_time = std::chrono::steady_clock::now();
4293
4294
4/4
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 9320 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 2 times.
9331 if (!srv_validate_tablespace_paths && !recv_needed_recovery) {
4295
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 ib::info(ER_IB_TABLESPACE_PATH_VALIDATION_SKIPPED);
4296 }
4297
4298 using std::placeholders::_1;
4299 using std::placeholders::_2;
4300 using std::placeholders::_3;
4301
4302 std::function<void(const Validate_files::Const_iter &,
4303 const Validate_files::Const_iter &, size_t)>
4304
2/4
✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9331 times.
✗ Branch 3 not taken.
9331 check = std::bind(&Validate_files::check, this, _1, _2, _3);
4305
4306
1/2
✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
9331 par_for(PFS_NOT_INSTRUMENTED, tablespaces, m_n_threads, check);
4307
4308
1/2
✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
9331 std::ostringstream msg;
4309
2/4
✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9331 times.
✗ Branch 3 not taken.
9331 msg << "Scanned " << m_n_to_check << " tablespaces."
4310
4/8
✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9331 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9331 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9331 times.
✗ Branch 7 not taken.
18662 << " Validated " << m_n_validated.load() << ".";
4311
4312
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 9307 times.
18662 if (m_n_skipped.load() > 0) {
4313
3/6
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
48 msg << " Skipped " << m_n_skipped.load() << ".";
4314 }
4315
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 9303 times.
18662 if (m_n_moved.load() > 0) {
4316
3/6
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
56 msg << " Found " << m_n_moved.load() << " moved.";
4317 }
4318
2/2
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 9224 times.
18662 if (m_n_missing.load() > 0) {
4319
3/6
✓ Branch 0 taken 107 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 107 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 107 times.
✗ Branch 5 not taken.
214 msg << " Found " << m_n_missing.load() << " missing.";
4320 }
4321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9331 times.
18662 if (m_n_deleted.load() > 0) {
4322 msg << " Found " << m_n_deleted.load() << " deleted.";
4323 }
4324
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9331 times.
18662 if (m_n_errors.load() > 0) {
4325 msg << " Encountered " << m_n_errors.load() << " errors.";
4326 }
4327
3/6
✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9331 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9331 times.
✗ Branch 5 not taken.
9331 ib::info(ER_IB_MSG_531) << msg.str();
4328
4329
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9331 times.
9331 if (failed()) {
4330 return (DB_ERROR);
4331 }
4332
4333
1/2
✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
9331 fil_set_max_space_id_if_bigger(get_space_max_id());
4334
4335
2/2
✓ Branch 0 taken 9320 times.
✓ Branch 1 taken 11 times.
9331 if (srv_validate_tablespace_paths) {
4336 9320 clone_sys->set_space_initialized();
4337 }
4338
4339 9331 return (DB_SUCCESS);
4340 9331 }
4341
4342 /** Discover all InnoDB tablespaces.
4343 @param[in,out] thd thread handle
4344 @retval true on error
4345 @retval false on success */
4346 9331 [[nodiscard]] static bool boot_tablespaces(THD *thd) {
4347
1/2
✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
9331 auto dc = dd::get_dd_client(thd);
4348
4349 using DD_tablespaces = std::vector<const dd::Tablespace *>;
4350 using Releaser = dd::cache::Dictionary_client::Auto_releaser;
4351
4352 9331 DD_tablespaces tablespaces;
4353
1/2
✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
9331 Releaser releaser(dc);
4354
4355 /* Initialize the max space_id from sys header */
4356
1/2
✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
9331 dict_sys_mutex_enter();
4357
4358
1/2
✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
9331 mtr_t mtr;
4359
4360
1/2
✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
9331 mtr_start(&mtr);
4361
4362
2/4
✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9331 times.
✗ Branch 3 not taken.
9331 space_id_t space_max_id = mtr_read_ulint(
4363 dict_hdr_get(&mtr) + DICT_HDR_MAX_SPACE_ID, MLOG_4BYTES, &mtr);
4364
4365
1/2
✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
9331 mtr_commit(&mtr);
4366
4367
1/2
✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
9331 fil_set_max_space_id_if_bigger(space_max_id);
4368
4369
1/2
✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
9331 dict_sys_mutex_exit();
4370
4371
2/4
✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9331 times.
✗ Branch 3 not taken.
9331 ib::info(ER_IB_MSG_532) << "Reading DD tablespace files";
4372
4373
2/4
✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9331 times.
9331 if (dc->fetch_global_components(&tablespaces)) {
4374 /* Failed to fetch the tablespaces from the DD. */
4375
4376 return (DD_FAILURE);
4377 }
4378
4379 9331 Validate_files validator;
4380
1/2
✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
9331 dberr_t err = validator.validate(tablespaces);
4381
4382
1/2
✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
9331 return (err == DB_SUCCESS ? DD_SUCCESS : DD_FAILURE);
4383 9331 }
4384
4385 /** Create metadata for a predefined tablespace at server initialization.
4386 @param[in,out] dd_client data dictionary client
4387 @param[in] space_id InnoDB tablespace ID
4388 @param[in] flags tablespace flags
4389 @param[in] name tablespace name
4390 @param[in] filename tablespace file name
4391 @retval false on success
4392 @retval true on failure */
4393 849 static bool predefine_tablespace(dd::cache::Dictionary_client *dd_client,
4394 space_id_t space_id, uint32_t flags,
4395 const char *name, const char *filename) {
4396 dd::Object_id dd_space_id;
4397
4398
1/2
✓ Branch 0 taken 849 times.
✗ Branch 1 not taken.
849 return (dd_create_tablespace(dd_client, name, space_id, flags, filename,
4399 1698 false, dd_space_id));
4400 }
4401
4402 /** Check if InnoDB is in a mode where the data dictionary is read-only.
4403 @return true if srv_read_only_mode is true or if srv_force_recovery > 0 */
4404 97477 static bool innobase_is_dict_readonly() {
4405
1/2
✓ Branch 0 taken 97477 times.
✗ Branch 1 not taken.
97477 DBUG_TRACE;
4406
4/4
✓ Branch 0 taken 97202 times.
✓ Branch 1 taken 275 times.
✓ Branch 2 taken 112 times.
✓ Branch 3 taken 97090 times.
194954 return srv_read_only_mode || srv_force_recovery > 0;
4407 97477 }
4408
4409 #ifndef UNIV_HOTBACKUP
4410 /** Update metadata for innodb_temporary tablespace at server startup.
4411 This information is used by the information_schema.files to show the
4412 filename for the temporary tablespace innodb_temporary.
4413 @param[in,out] thd THD
4414 @retval false on success
4415 @retval true on failure */
4416 9614 static bool update_innodb_temporary_metadata(THD *thd) {
4417
3/4
✓ Branch 0 taken 9614 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
✓ Branch 3 taken 9557 times.
9614 if (innobase_is_dict_readonly()) {
4418 /* Metadata cannot be updated if the server is started in read_only
4419 mode. This means that the values for innodb_temp_data_file_path and
4420 file_name in information_schema.files will not be in same. */
4421
8/16
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 57 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 57 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 57 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 57 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 57 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 57 times.
✗ Branch 15 not taken.
57 LogErr(WARNING_LEVEL, ER_SKIP_UPDATING_METADATA_IN_SE_RO_MODE,
4422 "information_schema");
4423 57 return false;
4424 }
4425
4426 /* Get the filename from srv_tmp_space */
4427
1/2
✓ Branch 0 taken 9557 times.
✗ Branch 1 not taken.
9557 auto fpath = srv_tmp_space.first_datafile()->filepath();
4428 9557 auto &dc = *thd->dd_client();
4429
1/2
✓ Branch 0 taken 9557 times.
✗ Branch 1 not taken.
9557 dd::cache::Dictionary_client::Auto_releaser releaser(&dc);
4430
1/2
✓ Branch 0 taken 9557 times.
✗ Branch 1 not taken.
9557 const dd::String_type tbsp_name{dict_sys_t::s_temp_space_name};
4431 9557 dd::Tablespace *tmp_tbsp{nullptr};
4432
4433
3/6
✓ Branch 0 taken 9557 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9557 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9557 times.
✗ Branch 5 not taken.
19114 if (!dc.acquire_for_modification<dd::Tablespace>(tbsp_name, &tmp_tbsp) &&
4434
1/2
✓ Branch 0 taken 9557 times.
✗ Branch 1 not taken.
9557 tmp_tbsp != nullptr) {
4435
2/4
✓ Branch 0 taken 9557 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9557 times.
9557 ut_ad(tmp_tbsp->files().size() == 1);
4436
4437 /* Get the tablespace file for innodb_temporary tablespace. */
4438 dd::Tablespace_file *dd_file =
4439
3/6
✓ Branch 0 taken 9557 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9557 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9557 times.
✗ Branch 5 not taken.
9557 const_cast<dd::Tablespace_file *>(*(tmp_tbsp->files().begin()));
4440
4441
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9557 times.
9557 ut_ad(dd_file);
4442
4443
2/4
✓ Branch 0 taken 9557 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9557 times.
✗ Branch 3 not taken.
9557 dd_file->set_filename(fpath);
4444
4445
2/4
✓ Branch 0 taken 9557 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9557 times.
9557 if (dc.update(tmp_tbsp)) {
4446 /* Unable to update the metadata. */
4447 ut_d(ut_error);
4448 ut_o(return true);
4449 }
4450 } else {
4451 /* Unable to acquire innodb_temporary tablespace for modification. */
4452 ut_d(ut_error);
4453 ut_o(return true);
4454 }
4455 9557 return false;
4456 9557 }
4457 #endif /* !UNIV_HOTBACKUP */
4458
4459 /** Predefine the undo tablespace metadata at server initialization.
4460 @param[in,out] dd_client data dictionary client
4461 @retval false on success
4462 @retval true on failure */
4463 283 static bool predefine_undo_tablespaces(
4464 dd::cache::Dictionary_client *dd_client) {
4465 /** Undo tablespaces use a reserved range of tablespace ID. */
4466
2/2
✓ Branch 0 taken 566 times.
✓ Branch 1 taken 283 times.
849 for (auto undo_space : undo::spaces->m_spaces) {
4467
1/2
✓ Branch 0 taken 566 times.
✗ Branch 1 not taken.
566 uint32_t flags = fsp_flags_init(univ_page_size, false, false, false, false);
4468
4469
2/4
✓ Branch 0 taken 566 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 566 times.
566 if (predefine_tablespace(dd_client, undo_space->id(), flags,
4470 566 undo_space->space_name(),
4471
2/4
✓ Branch 0 taken 566 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 566 times.
✗ Branch 3 not taken.
566 undo_space->file_name())) {
4472 return (true);
4473 }
4474 }
4475
4476 283 return (false);
4477 }
4478
4479 /** Invalidate an entry or entries for partitoined table from the dict cache.
4480 @param[in] schema_name Schema name
4481 @param[in] table_name Table name */
4482 278605 static void innobase_dict_cache_reset(const char *schema_name,
4483 const char *table_name) {
4484 char name[FN_REFLEN];
4485 278605 snprintf(name, sizeof name, "%s/%s", schema_name, table_name);
4486
4487
1/2
✓ Branch 0 taken 278605 times.
✗ Branch 1 not taken.
278605 dict_sys_mutex_enter();
4488
4489
1/2
✓ Branch 0 taken 278605 times.
✗ Branch 1 not taken.
278605 dict_table_t *table = dict_table_check_if_in_cache_low(name);
4490
4491
2/2
✓ Branch 0 taken 163452 times.
✓ Branch 1 taken 115153 times.
278605 if (table != nullptr) {
4492
1/2
✓ Branch 0 taken 163452 times.
✗ Branch 1 not taken.
163452 btr_drop_ahi_for_table(table);
4493
1/2
✓ Branch 0 taken 163452 times.
✗ Branch 1 not taken.
163452 dict_table_remove_from_cache(table);
4494
2/2
✓ Branch 0 taken 2791 times.
✓ Branch 1 taken 112362 times.
115153 } else if (strcmp(schema_name, "mysql") != 0) {
4495
1/2
✓ Branch 0 taken 2791 times.
✗ Branch 1 not taken.
2791 dict_partitioned_table_remove_from_cache(name);
4496 }
4497
4498
1/2
✓ Branch 0 taken 278605 times.
✗ Branch 1 not taken.
278605 dict_sys_mutex_exit();
4499 278605 }
4500
4501 /** Invalidate user table dict cache after Replication Plugin recovers. Table
4502 definition could be different with XA commit/rollback of DDL operations */
4503 9493 static void innobase_dict_cache_reset_tables_and_tablespaces() {
4504 9493 dict_sys_mutex_enter();
4505
4506 /* There should be no DDL/DML activity at this stage, so access
4507 the LRU chain without mutex. We only invalidates the table
4508 in LRU list */
4509
7/12
✓ Branch 0 taken 9493 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9493 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9493 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 186211 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 195704 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 186211 times.
✓ Branch 11 taken 9493 times.
195704 for (auto table : dict_sys->table_LRU.removable()) {
4510 /* Make sure table->is_dd_table is set */
4511
4512 186211 std::string db_str;
4513 186211 std::string tbl_str;
4514
2/4
✓ Branch 0 taken 186211 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 186211 times.
✗ Branch 3 not taken.
186211 dict_name::get_table(table->name.m_name, db_str, tbl_str);
4515
4516 /* TODO: Remove follow if we have better way to identify
4517 DD "system table" */
4518
1/2
✓ Branch 0 taken 20930 times.
✗ Branch 1 not taken.
207141 if (db_str.compare("mysql") == 0 || table->is_dd_table ||
4519
9/10
✓ Branch 0 taken 20930 times.
✓ Branch 1 taken 165281 times.
✓ Branch 2 taken 20930 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20929 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1315 times.
✓ Branch 7 taken 19614 times.
✓ Branch 8 taken 166597 times.
✓ Branch 9 taken 19614 times.
228070 table->is_corrupted() ||
4520 20929 DICT_TF2_FLAG_IS_SET(table, DICT_TF2_RESURRECT_PREPARED)) {
4521 166597 continue;
4522 }
4523
4524
1/2
✓ Branch 0 taken 19614 times.
✗ Branch 1 not taken.
19614 table->acquire();
4525
1/2
✓ Branch 0 taken 19614 times.
✗ Branch 1 not taken.
19614 btr_drop_ahi_for_table(table);
4526
1/2
✓ Branch 0 taken 19614 times.
✗ Branch 1 not taken.
19614 dd_table_close(table, nullptr, nullptr, true);
4527
4528
1/2
✓ Branch 0 taken 19614 times.
✗ Branch 1 not taken.
19614 dict_table_remove_from_cache(table);
4529
4/4
✓ Branch 0 taken 19614 times.
✓ Branch 1 taken 166597 times.
✓ Branch 2 taken 19614 times.
✓ Branch 3 taken 166597 times.
352808 }
4530 9493 dict_sys_mutex_exit();
4531 9493 }
4532
4533 /** Perform high-level recovery in InnoDB as part of initializing the
4534 data dictionary.
4535 @param[in] dict_recovery_mode How to do recovery
4536 @param[in] version Target DD version if a new
4537 server is being installed.
4538 Actual DD version if restarting
4539 an existing server.
4540 @retval true An error occurred.
4541 @retval false Success - no errors. */
4542 9897 static bool innobase_dict_recover(dict_recovery_mode_t dict_recovery_mode,
4543 uint version [[maybe_unused]]) {
4544 9897 THD *thd = current_thd;
4545
4546
2/3
✓ Branch 0 taken 283 times.
✓ Branch 1 taken 9614 times.
✗ Branch 2 not taken.
9897 switch (dict_recovery_mode) {
4547 283 case DICT_RECOVERY_INITIALIZE_TABLESPACES:
4548 283 break;
4549 9614 case DICT_RECOVERY_RESTART_SERVER:
4550 [[fallthrough]];
4551 case DICT_RECOVERY_INITIALIZE_SERVER:
4552
2/2
✓ Branch 0 taken 8097 times.
✓ Branch 1 taken 1517 times.
9614 if (dict_sys->dynamic_metadata == nullptr) {
4553 16194 dict_sys->dynamic_metadata =
4554 8097 dd_table_open_on_name(thd, nullptr, "mysql/innodb_dynamic_metadata",
4555 false, DICT_ERR_IGNORE_NONE);
4556 16194 dict_persist->table_buffer =
4557 8097 ut::new_withkey<DDTableBuffer>(UT_NEW_THIS_FILE_PSI_KEY);
4558 }
4559
4560 19228 dict_sys->table_stats =
4561 9614 dd_table_open_on_name(thd, nullptr, "mysql/innodb_table_stats", false,
4562 DICT_ERR_IGNORE_NONE);
4563 19228 dict_sys->index_stats =
4564 9614 dd_table_open_on_name(thd, nullptr, "mysql/innodb_index_stats", false,
4565 DICT_ERR_IGNORE_NONE);
4566 9614 dict_sys->ddl_log = dd_table_open_on_name(
4567 thd, nullptr, "mysql/innodb_ddl_log", false, DICT_ERR_IGNORE_NONE);
4568 9614 log_ddl = ut::new_withkey<Log_DDL>(UT_NEW_THIS_FILE_PSI_KEY);
4569 }
4570
4571
3/4
✓ Branch 0 taken 283 times.
✓ Branch 1 taken 283 times.
✓ Branch 2 taken 9331 times.
✗ Branch 3 not taken.
9897 switch (dict_recovery_mode) {
4572 283 case DICT_RECOVERY_INITIALIZE_SERVER:
4573 283 return (false);
4574 283 case DICT_RECOVERY_INITIALIZE_TABLESPACES: {
4575
1/2
✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
283 dd::cache::Dictionary_client *client = dd::get_dd_client(thd);
4576
1/2
✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
283 dd::cache::Dictionary_client::Auto_releaser releaser(client);
4577
4578
2/4
✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 283 times.
283 if (predefine_tablespace(client, dict_sys_t::s_temp_space_id,
4579 srv_tmp_space.flags(),
4580 dict_sys_t::s_temp_space_name,
4581 dict_sys_t::s_temp_space_file_name)) {
4582 return (DD_FAILURE);
4583 }
4584
4585
2/4
✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 283 times.
283 if (predefine_undo_tablespaces(client)) {
4586 return (DD_FAILURE);
4587 }
4588
4589 283 break;
4590
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 283 times.
283 }
4591 9331 case DICT_RECOVERY_RESTART_SERVER:
4592 /* Traverse dd::tablespaces and apply/validate this metadata. */
4593
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9331 times.
9331 if (boot_tablespaces(thd)) {
4594 return (true);
4595 }
4596
4597 #ifndef UNIV_HOTBACKUP
4598 /* For all tablespaces for which tablespace key is to be reencrypt,
4599 do it now. */
4600 9331 fil_encryption_reencrypt(Encryption::s_tablespaces_to_reencrypt);
4601 #endif /* !UNIV_HOTBACKUP */
4602
4603 /* We might need to fix tables for CSV and MyISAM SE */
4604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9331 times.
9331 if (fix_cloned_tables(thd)) {
4605 return (true);
4606 }
4607
4608 9331 srv_dict_recover_on_restart();
4609 }
4610
4611 9614 srv_start_threads(dict_recovery_mode != DICT_RECOVERY_RESTART_SERVER);
4612
4613 #ifndef UNIV_HOTBACKUP
4614 /* Update the metadata for innodb_temporary tablespace to reflect
4615 the correct filename. */
4616
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9614 times.
9614 if (update_innodb_temporary_metadata(thd)) {
4617 return true;
4618 }
4619 #endif /* !UNIV_HOTBACKUP */
4620
4621 9614 return (fil_open_for_business(srv_read_only_mode) != DB_SUCCESS);
4622 }
4623
4624 /** DDL crash recovery: process the records recovered from "log_ddl" table */
4625 9493 static void innobase_post_recover() {
4626
2/2
✓ Branch 0 taken 9477 times.
✓ Branch 1 taken 16 times.
9493 if (srv_force_recovery < SRV_FORCE_NO_TRX_UNDO) {
4627
2/4
✓ Branch 0 taken 9477 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9477 times.
9477 DBUG_EXECUTE_IF("DDL_Log_remove_inject_startup_error_2",
4628 srv_inject_too_many_concurrent_trxs = true;);
4629
4630
1/2
✓ Branch 0 taken 9477 times.
✗ Branch 1 not taken.
9477 dberr_t err = log_ddl->recover();
4631
4632 /* Abort post recovery startup if this is not successful. */
4633
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9477 times.
9477 if (err != DB_SUCCESS) {
4634 ib::fatal(UT_LOCATION_HERE, ER_IB_MSG_POST_RECOVER_DDL_LOG_RECOVER);
4635 }
4636 }
4637
4638
1/2
✓ Branch 0 taken 9493 times.
✗ Branch 1 not taken.
9493 fil_free_scanned_files();
4639
4640 /* If undo tablespaces are to be encrypted, encrypt them now */
4641
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 9453 times.
9493 if (srv_undo_log_encrypt) {
4642
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 ut_ad(Encryption::check_keyring());
4643
4644 /* There would be at least 2 UNDO tablespaces */
4645
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 ut_ad(undo::spaces->size() >= FSP_IMPLICIT_UNDO_TABLESPACES);
4646
4647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (srv_read_only_mode) {
4648 ib::error(ER_IB_MSG_1051);
4649 srv_undo_log_encrypt = false;
4650 } else {
4651 /* Enable encryption for UNDO tablespaces */
4652
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 mutex_enter(&undo::ddl_mutex);
4653
2/4
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 40 times.
40 if (srv_enable_undo_encryption(nullptr)) {
4654 srv_undo_log_encrypt = false;
4655 ut_d(ut_error);
4656 }
4657
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 mutex_exit(&undo::ddl_mutex);
4658
4659 /* We have to ensure that the first page of the undo tablespaces gets
4660 flushed to disk. Otherwise during recovery, since we read the first
4661 page without applying the redo logs, it will be determined that
4662 encryption is off. */
4663
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 buf_flush_sync_all_buf_pools();
4664 }
4665 }
4666
4667 /* If redo log is to be encrypted, encrypt it now */
4668
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 9450 times.
9493 if (srv_redo_log_encrypt) {
4669
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 ut_ad(Encryption::check_keyring());
4670
4671
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (srv_read_only_mode) {
4672 ib::error(ER_IB_MSG_LOG_FILES_CANNOT_ENCRYPT_IN_READ_ONLY);
4673 srv_redo_log_encrypt = false;
4674 } else {
4675 /* Enable encryption for REDO log */
4676
2/4
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 43 times.
43 if (srv_enable_redo_encryption()) {
4677 srv_redo_log_encrypt = false;
4678 ut_d(ut_error);
4679 }
4680 }
4681 }
4682
4683
4/4
✓ Branch 0 taken 9455 times.
✓ Branch 1 taken 38 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 9445 times.
9493 if (srv_read_only_mode || srv_force_recovery >= SRV_FORCE_NO_BACKGROUND) {
4684 48 purge_sys->state = PURGE_STATE_DISABLED;
4685 48 return;
4686 }
4687
4688
1/2
✓ Branch 0 taken 9445 times.
✗ Branch 1 not taken.
9445 Auto_THD thd;
4689
2/4
✓ Branch 0 taken 9445 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9445 times.
9445 if (dd_tablespace_update_cache(thd.thd)) {
4690 ut_d(ut_error);
4691 }
4692
4693
1/2
✓ Branch 0 taken 9443 times.
✗ Branch 1 not taken.
9445 srv_start_threads_after_ddl_recovery();
4694
4695
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9443 times.
9443 ut_a(innodb_inited);
4696
4697
2/2
✓ Branch 0 taken 9241 times.
✓ Branch 1 taken 202 times.
9443 if (!opt_initialize) {
4698
2/4
✓ Branch 0 taken 9233 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9233 times.
9241 if (!log_pfs_create_tables()) {
4699 ib::warn(ER_IB_MSG_LOG_PFS_CREATE_TABLES_FAILED);
4700 }
4701 }
4702 9435 }
4703
4704 /**
4705 Get the server version id stored in the header of the
4706 dictionary tablespace.
4707
4708 @param [out] version Version number from the DD
4709 tablespace header.
4710
4711 @retval Operation outcome, false if no error, otherwise true.
4712 */
4713 19135 static bool innobase_dict_get_server_version(uint *version) {
4714 19135 return (fsp_header_dict_get_server_version(version));
4715 }
4716
4717 /**
4718 Store the current server version number into the
4719 header of the dictionary tablespace.
4720
4721 @retval Operation outcome, false if no error, otherwise true.
4722 */
4723 167 static bool innobase_dict_set_server_version() {
4724 /* Update the server version number, but leave the space version unchanged */
4725 167 return (upgrade_space_version(dict_sys_t::s_dict_space_id, true));
4726 }
4727
4728 /** Start page tracking.
4729 @param[out] start_id LSN indicating when the tracking was started
4730 @return Operation status.
4731 @retval 0 Success
4732 @retval other ER_* mysql error. Get error details from THD. */
4733 static int innobase_page_track_start(uint64_t *start_id) {
4734 if (srv_read_only_mode) {
4735 my_error(ER_READ_ONLY_MODE, MYF(0));
4736 return ER_READ_ONLY_MODE;
4737 }
4738
4739 Page_Arch_Client_Ctx *ctx = arch_page_sys->get_sys_client();
4740
4741 int err = ctx->start(false, start_id);
4742
4743 return (err);
4744 }
4745
4746 /** Stop page tracking.
4747 @param[out] stop_id Stop LSN indicating when the tracking was stopped
4748 @return Operation status.
4749 @retval 0 Success
4750 @retval other ER_* mysql error. Get error details from THD. */
4751 static int innobase_page_track_stop(uint64_t *stop_id) {
4752 if (srv_read_only_mode) {
4753 my_error(ER_READ_ONLY_MODE, MYF(0));
4754 return ER_READ_ONLY_MODE;
4755 }
4756
4757 Page_Arch_Client_Ctx *ctx = arch_page_sys->get_sys_client();
4758
4759 int err = ctx->stop(stop_id);
4760
4761 return (err);
4762 }
4763
4764 /** Purge page tracking data.
4765 @param[in,out] purge_id Purge LSN initially indicating till where the data
4766 needs to be purged and finally updated to until where it was actually purged
4767 @return Operation status.
4768 @retval 0 Success
4769 @retval other ER_* mysql error. Get error details from THD. */
4770 static int innobase_page_track_purge(uint64_t *purge_id) {
4771 if (srv_read_only_mode) {
4772 my_error(ER_READ_ONLY_MODE, MYF(0));
4773 return ER_READ_ONLY_MODE;
4774 }
4775
4776 auto err = arch_page_sys->purge(purge_id);
4777
4778 return (err);
4779 }
4780
4781 /** Fetch tracked pages.
4782 @param[in] cbk_func callback function return page IDs
4783 @param[in] cbk_ctx caller's context for callback
4784 @param[in,out] start_id SE specific sequence number [LSN for Innodb] from
4785 where the pages tracked would be returned.
4786 @note The range might get expanded and the actual start_id used for the
4787 querying will be updated.
4788 @param[in,out] stop_id SE specific sequence number [LSN for Innodb]
4789 until where the pages tracked would be returned.
4790 @note The range might get expanded and the actual stop_id used for the
4791 querying will be updated.
4792 @param[out] buffer allocated buffer to copy page IDs
4793 @param[in] buffer_len length of buffer in bytes
4794 @return Operation status.
4795 @retval 0 Success
4796 @retval other ER_* mysql error. Get error details from THD. */
4797 static int innobase_page_track_get_page_ids(Page_Track_Callback cbk_func,
4798 void *cbk_ctx, uint64_t *start_id,
4799 uint64_t *stop_id,
4800 unsigned char *buffer,
4801 size_t buffer_len) {
4802 if (srv_read_only_mode) {
4803 my_error(ER_READ_ONLY_MODE, MYF(0));
4804 return ER_READ_ONLY_MODE;
4805 }
4806
4807 auto err =
4808 arch_page_sys->get_pages(nullptr, cbk_func, cbk_ctx, *start_id, *stop_id,
4809 buffer, static_cast<uint>(buffer_len));
4810
4811 if (err != 0) {
4812 DBUG_PRINT("page_archiver", ("Fetch Pages"));
4813 DBUG_PRINT("page_archiver", ("Can't fetch pages"));
4814 }
4815
4816 return (err);
4817 }
4818
4819 /** Fetch approximate number of tracked pages in the given range.
4820 @param[in,out] start_id SE specific sequence number [LSN for Innodb] from
4821 where the pages tracked would be returned.
4822 @note the range might get expanded and the actual start_id used for the
4823 querying will be updated.
4824 @param[in,out] stop_id SE specific sequence number [LSN for Innodb]
4825 until where the pages tracked would be returned.
4826 @note the range might get expanded and the actual stop_id used for the
4827 querying will be updated.
4828 @param[out] num_pages number of pages tracked
4829 @return Operation status.
4830 @retval 0 Success
4831 @retval other ER_* mysql error. Get error details from THD. */
4832 static int innobase_page_track_get_num_page_ids(uint64_t *start_id,
4833 uint64_t *stop_id,
4834 uint64_t *num_pages) {
4835 if (srv_read_only_mode) {
4836 my_error(ER_READ_ONLY_MODE, MYF(0));
4837 return ER_READ_ONLY_MODE;
4838 }
4839
4840 auto err = arch_page_sys->get_num_pages(*start_id, *stop_id, num_pages);
4841
4842 if (err != 0) {
4843 DBUG_PRINT("page_archiver", ("Fetch Pages"));
4844 DBUG_PRINT("page_archiver", ("Can't fetch pages"));
4845 }
4846
4847 return (err);
4848 }
4849
4850 /** Fetch the page tracking status.
4851 @param[out] status vector of a pair of (ID, bool) where ID is the
4852 start/stop point and bool is true if the ID is a start point else false */
4853 static void innobase_page_track_get_status(
4854 std::vector<std::pair<lsn_t, bool>> &status) {
4855 if (srv_read_only_mode) {
4856 my_error(ER_READ_ONLY_MODE, MYF(0));
4857 return;
4858 }
4859
4860 arch_page_sys->get_status(status);
4861 }
4862
4863 /** Gives the file extension of an InnoDB single-table tablespace. */
4864 static const char *ha_innobase_exts[] = {dot_ext[IBD], NullS};
4865
4866 /** This function checks if the given db.tablename is a system table
4867 supported by Innodb and is used as an initializer for the data member
4868 is_supported_system_table of InnoDB storage engine handlerton.
4869 Except general_log and slow_log, currently all system tables are supported
4870 by InnoDB. Please don't add any SE-specific system tables here.
4871
4872 @param is_sql_layer_system_table if the supplied db.table_name is a SQL
4873 layer system table.
4874
4875 @return whether the table name is supported */
4876
4877 1031468 static bool innobase_is_supported_system_table(const char *, const char *,
4878 bool is_sql_layer_system_table) {
4879 // Currently InnoDB does not support any other SE specific system tables.
4880 1031468 return is_sql_layer_system_table;
4881 }
4882
4883 /** Rotate the encrypted tablespace keys according to master key
4884 rotation.
4885 @return false on success, true on failure */
4886 1182 bool innobase_encryption_key_rotation() {
4887 1182 byte *master_key = nullptr;
4888 1182 bool ret = false;
4889 dberr_t err;
4890
4891 /* Pause here to try other locks while this thread holds the backup locks. */
4892
2/4
✓ Branch 0 taken 1182 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1182 times.
✗ Branch 3 not taken.
1182 DEBUG_SYNC_C("ib_pause_encryption_rotate");
4893
4894
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1182 times.
1182 if (srv_read_only_mode) {
4895 my_error(ER_INNODB_READ_ONLY, MYF(0));
4896 return (true);
4897 }
4898
4899 /* Take mutex as master_key_id is going to be changed. */
4900
1/2
✓ Branch 0 taken 1182 times.
✗ Branch 1 not taken.
1182 mutex_enter(&master_key_id_mutex);
4901
4902 /* Check if keyring loaded and the currently master key
4903 can be fetched. */
4904
3/4
✓ Branch 0 taken 1182 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1163 times.
✓ Branch 3 taken 19 times.
1182 if (Encryption::get_master_key_id() != Encryption::DEFAULT_MASTER_KEY_ID) {
4905 uint32_t master_key_id;
4906
4907 1163 Encryption::get_master_key(&master_key_id, &master_key);
4908
4909
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1148 times.
1163 if (master_key == nullptr) {
4910
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0));
4911 15 ret = true;
4912 15 goto error_exit;
4913 }
4914
1/2
✓ Branch 0 taken 1148 times.
✗ Branch 1 not taken.
1148 my_free(master_key);
4915 }
4916
4917 1167 master_key = nullptr;
4918
4919 /* Generate the new master key. */
4920 1167 Encryption::create_master_key(&master_key);
4921
4922
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1154 times.
1165 if (master_key == nullptr) {
4923
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0));
4924 11 ret = true;
4925 11 goto error_exit;
4926 }
4927
4928 /* Rotate all IBD and IBU tablespace that need it. */
4929
2/4
✓ Branch 0 taken 1150 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1150 times.
1154 if (fil_encryption_rotate() > 0) {
4930 my_free(master_key);
4931 my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0));
4932 goto error_exit;
4933 }
4934
4935
1/2
✓ Branch 0 taken 1150 times.
✗ Branch 1 not taken.
1150 err = log_encryption_on_master_key_changed(*log_sys);
4936 1150 ret = (err != DB_SUCCESS);
4937
4938 /* If rotation failure, return error */
4939
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1150 times.
1150 if (ret) {
4940 my_free(master_key);
4941 my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0));
4942 goto error_exit;
4943 }
4944
4945 /* Rotate encrypted session temporary tablespaces */
4946
1/2
✓ Branch 0 taken 1150 times.
✗ Branch 1 not taken.
1150 ibt::tbsp_pool->rotate_encryption_keys();
4947
4948
1/2
✓ Branch 0 taken 1150 times.
✗ Branch 1 not taken.
1150 my_free(master_key);
4949
4950 1176 error_exit:
4951 /* Release the mutex. */
4952
1/2
✓ Branch 0 taken 1176 times.
✗ Branch 1 not taken.
1176 mutex_exit(&master_key_id_mutex);
4953
4954 1176 return (ret);
4955 }
4956
4957 9498 bool innobase_fix_default_table_encryption(ulong encryption_option,
4958 bool is_server_starting) {
4959
2/2
✓ Branch 0 taken 9460 times.
✓ Branch 1 taken 38 times.
9498 if (!srv_read_only_mode) {
4960 9460 return fil_crypt_set_encrypt_tables(
4961 static_cast<enum_default_table_encryption>(encryption_option),
4962 9460 is_server_starting);
4963 }
4964 38 return false;
4965 }
4966
4967 /** Fix the empty UUID of tablespaces like system, temp etc by generating
4968 a new master key and do key rotation. These tablespaces if encrypted
4969 during startup, will be encrypted with tablespace key which has empty UUID
4970 @return false on success, true on failure */
4971 9450 bool innobase_fix_tablespaces_empty_uuid() {
4972 #ifdef UNIV_DEBUG
4973 /* This API is called only after uuid is ready */
4974 9450 srv_is_uuid_ready = true;
4975 #endif /* UNIV_DEBUG */
4976
4977 /* If we are in read only mode, we cannot do rotation but it
4978 is OK */
4979
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 9412 times.
9450 if (srv_read_only_mode) {
4980 38 return (false);
4981 }
4982
4983 /* We only need to handle the case when an encrypted tablespace
4984 is created at startup. If it is > 1, it means we already have fixed
4985 the UUID */
4986
3/4
✓ Branch 0 taken 9412 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 53 times.
✓ Branch 3 taken 9359 times.
9412 if (Encryption::get_master_key_id() > 1) {
4987 53 return (false);
4988 }
4989
4990
1/2
✓ Branch 0 taken 9359 times.
✗ Branch 1 not taken.
9359 if (!default_master_key_used) {
4991 9359 return (false);
4992 }
4993
4994 byte *master_key = nullptr;
4995 uint32_t master_key_id;
4996 Encryption::get_master_key(&master_key_id, &master_key);
4997
4998 if (master_key == nullptr) {
4999 my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0));
5000 return (true);
5001 }
5002 my_free(master_key);
5003
5004 master_key = nullptr;
5005
5006 /* Generate the new master key. */
5007 Encryption::create_master_key(&master_key);
5008
5009 if (master_key == nullptr) {
5010 my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0));
5011 return (true);
5012 }
5013
5014 /** Check if sys, temp need rotation to fix the empty uuid */
5015 space_id_vec space_ids;
5016
5017 space_ids.push_back(srv_sys_space.space_id());
5018 space_ids.push_back(srv_tmp_space.space_id());
5019 space_ids.push_back(dict_sys_t::s_dict_space_id);
5020
5021 #ifdef UNIV_DEBUG
5022 /* Currently all session temp tablespaces that use empty uuid
5023 are destroyed. So if there is encrypted sesion temp tablespace
5024 we assert here */
5025 const auto find_encrypted = [&](const ibt::Tablespace *ts) {
5026 if (ts->is_encrypted()) {
5027 ut_ad(0);
5028 }
5029 };
5030
5031 ibt::tbsp_pool->iterate_active_tbsp(find_encrypted);
5032 #endif /* UNIV_DEBUG */
5033
5034 undo::spaces->s_lock();
5035 for (auto undo_space : undo::spaces->m_spaces) {
5036 /* We already added system tablespace */
5037 if (undo_space->id() == TRX_SYS_SPACE) {
5038 continue;
5039 }
5040 space_ids.push_back(undo_space->id());
5041 }
5042 undo::spaces->s_unlock();
5043
5044 /* Rotate log tablespace */
5045
5046 my_free(master_key);
5047
5048 return (false);
5049 }
5050
5051 /** Enable or Disable SE write ahead logging.
5052 @param[in] thd connection THD
5053 @param[in] enable enable/disable redo logging
5054 @return true iff failed. */
5055 38 static bool innobase_redo_set_state(THD *thd, bool enable) {
5056
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (srv_read_only_mode) {
5057 my_error(ER_INNODB_READ_ONLY, MYF(0));
5058 return (true);
5059 }
5060
5061 38 int err = 0;
5062
5063
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 20 times.
38 if (enable) {
5064 18 err = mtr_t::s_logging.enable(thd);
5065 } else {
5066 20 err = mtr_t::s_logging.disable(thd);
5067 }
5068
5069
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 36 times.
38 if (err != 0) {
5070 2 return (true);
5071 }
5072
5073 36 set_srv_redo_log(enable);
5074 36 return (false);
5075 }
5076
5077 /** Return partitioning flags. */
5078 2318064 static uint innobase_partition_flags() {
5079 return (HA_CAN_EXCHANGE_PARTITION | HA_CANNOT_PARTITION_FK |
5080 2318064 HA_TRUNCATE_PARTITION_PRECLOSE);
5081 }
5082 #endif /* !UNIV_HOTBACKUP */
5083
5084 /** Update log_checksum_algorithm_ptr with a pointer to the function
5085 corresponding to whether checksums are enabled.
5086 @param[in] check whether redo log block checksums are enabled */
5087 #ifndef UNIV_HOTBACKUP
5088 static
5089 #endif /* !UNIV_HOTBACKUP */
5090 void
5091 9733 innodb_log_checksums_func_update(bool check) {
5092
2/2
✓ Branch 0 taken 9729 times.
✓ Branch 1 taken 4 times.
9733 log_checksum_algorithm_ptr.store(check ? log_block_calc_checksum_crc32
5093 : log_block_calc_checksum_none);
5094 9733 }
5095
5096 #ifndef UNIV_HOTBACKUP
5097
5098 /** Minimum expected tablespace size. (5M) */
5099 static const ulint MIN_EXPECTED_TABLESPACE_SIZE = 5 * 1024 * 1024;
5100
5101 /** Validate innodb_undo_tablespaces. Log a warning if it was set
5102 explicitly. */
5103 9732 static void innodb_undo_tablespaces_deprecate() {
5104
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9732 times.
9732 if (sysvar_source_svc == nullptr) {
5105 return;
5106 }
5107
5108 static const char *variable_name = "innodb_undo_tablespaces";
5109 enum enum_variable_source source;
5110
5111
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9732 times.
9732 if (sysvar_source_svc->get(variable_name,
5112
1/2
✓ Branch 0 taken 9732 times.
✗ Branch 1 not taken.
9732 static_cast<unsigned int>(strlen(variable_name)),
5113 &source)) {
5114 return;
5115 }
5116
5117
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 9724 times.
9732 if (source != COMPILED) {
5118
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 ib::warn(ER_IB_MSG_DEPRECATED_INNODB_UNDO_TABLESPACES);
5119 8 srv_undo_tablespaces = FSP_IMPLICIT_UNDO_TABLESPACES;
5120 }
5121 }
5122
5123 /** Validate innodb_parallel_doublewrite_path. Log a warning if it was set
5124 explicitly. */
5125 9726 static void innodb_parallel_doublewrite_path_deprecate() {
5126
1/2
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
9726 if (sysvar_source_svc != nullptr) {
5127 static const char *variable_name = "innodb_parallel_doublewrite_path";
5128 enum enum_variable_source source;
5129
1/2
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
9726 if (!sysvar_source_svc->get(
5130
1/2
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
9726 variable_name, static_cast<unsigned int>(strlen(variable_name)),
5131 &source)) {
5132
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9725 times.
9726 if (source != COMPILED) {
5133
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 ib::warn(ER_IB_MSG_DEPRECATED_INNODB_PARALLEL_DOUBLEWRITE_PATH);
5134 }
5135 }
5136 }
5137 9726 }
5138
5139 /** Validate innodb_parallel_dblwr_encrypt. Log a warning if it was set
5140 explicitly. */
5141 9729 static void innodb_parallel_dblwr_encrypt_deprecate() {
5142
1/2
✓ Branch 0 taken 9729 times.
✗ Branch 1 not taken.
9729 if (sysvar_source_svc != nullptr) {
5143 static const char *variable_name = "innodb_parallel_dblwr_encrypt";
5144 enum enum_variable_source source;
5145
1/2
✓ Branch 0 taken 9729 times.
✗ Branch 1 not taken.
9729 if (!sysvar_source_svc->get(
5146
1/2
✓ Branch 0 taken 9729 times.
✗ Branch 1 not taken.
9729 variable_name, static_cast<unsigned int>(strlen(variable_name)),
5147 &source)) {
5148
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 9713 times.
9729 if (source != COMPILED) {
5149
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 ib::warn(ER_IB_MSG_DEPRECATED_INNODB_PARALLEL_DBLWR_ENCRYPT);
5150 }
5151 }
5152 }
5153 9729 }
5154
5155 /** Initialize and normalize innodb_buffer_pool_size. */
5156 9726 static void innodb_buffer_pool_size_init() {
5157 #ifdef UNIV_DEBUG
5158 9726 ulong srv_buf_pool_instances_org = srv_buf_pool_instances;
5159 #endif /* UNIV_DEBUG */
5160
5161 /* If innodb_dedicated_server == ON */
5162
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
9726 if (srv_dedicated_server && sysvar_source_svc != nullptr) {
5163 static const char *variable_name = "innodb_buffer_pool_size";
5164 enum enum_variable_source source;
5165 if (!sysvar_source_svc->get(
5166 variable_name, static_cast<unsigned int>(strlen(variable_name)),
5167 &source)) {
5168 if (source == COMPILED) {
5169 double server_mem = get_sys_mem();
5170
5171 if (server_mem < 1.0) {
5172 ;
5173 } else if (server_mem <= 4.0) {
5174 srv_buf_pool_size = static_cast<ulint>(server_mem * 0.5 * GB);
5175 } else
5176 srv_buf_pool_size = static_cast<ulint>(server_mem * 0.75 * GB);
5177 } else {
5178 ib::warn(ER_IB_MSG_533)
5179 << "Option innodb_dedicated_server"
5180 " is ignored for"
5181 " innodb_buffer_pool_size because"
5182 " innodb_buffer_pool_size="
5183 << srv_buf_pool_curr_size << " is specified explicitly.";
5184 }
5185 }
5186 }
5187
5188
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 9703 times.
9726 if (srv_buf_pool_size >= BUF_POOL_SIZE_THRESHOLD) {
5189
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 15 times.
23 if (srv_buf_pool_instances == srv_buf_pool_instances_default) {
5190 #if defined(_WIN32) && !defined(_WIN64)
5191 /* Do not allocate too large of a buffer pool on
5192 Windows 32-bit systems, which can have trouble
5193 allocating larger single contiguous memory blocks. */
5194 srv_buf_pool_instances =
5195 std::min(static_cast<ulong>(MAX_BUFFER_POOLS),
5196 static_cast<ulong>(srv_buf_pool_size / (128 * 1024 * 1024)));
5197 #else /* defined(_WIN32) && !defined(_WIN64) */
5198 /* Default to 8 instances when size > 1GB. */
5199 8 srv_buf_pool_instances = 8;
5200 #endif /* defined(_WIN32) && !defined(_WIN64) */
5201 }
5202 } else {
5203 /* If buffer pool is less than 1 GiB, assume fewer
5204 threads. Also use only one buffer pool instance. */
5205
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 9699 times.
9703 if (srv_buf_pool_instances != srv_buf_pool_instances_default &&
5206
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 srv_buf_pool_instances != 1) {
5207 /* We can't distinguish whether the user has explicitly
5208 started mysqld with --innodb-buffer-pool-instances=0,
5209 (srv_buf_pool_instances_default is 0) or has not
5210 specified that option at all. Thus we have the
5211 limitation that if the user started with =0, we
5212 will not emit a warning here, but we should actually
5213 do so. */
5214 2 ib::info(ER_IB_MSG_534)
5215 << "Adjusting innodb_buffer_pool_instances"
5216
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 " from "
5217
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 << srv_buf_pool_instances
5218 << " to 1"
5219
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 " since innodb_buffer_pool_size is less than "
5220
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 << BUF_POOL_SIZE_THRESHOLD / (1024 * 1024) << " MiB";
5221 }
5222
5223 9703 srv_buf_pool_instances = 1;
5224 }
5225
5226 #ifdef UNIV_DEBUG
5227
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9725 times.
9726 if (srv_buf_pool_debug &&
5228
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 srv_buf_pool_instances_org != srv_buf_pool_instances_default) {
5229 1 srv_buf_pool_instances = srv_buf_pool_instances_org;
5230 };
5231 #endif /* UNIV_DEBUG */
5232
5233 9726 srv_buf_pool_chunk_unit = buf_pool_adjust_chunk_unit(srv_buf_pool_chunk_unit);
5234 9726 srv_buf_pool_size = buf_pool_size_align(srv_buf_pool_size);
5235
5236
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 ut_ad(srv_buf_pool_chunk_unit >= srv_buf_pool_chunk_unit_min);
5237
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 ut_ad(srv_buf_pool_chunk_unit <= srv_buf_pool_chunk_unit_max);
5238
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 ut_ad(srv_buf_pool_chunk_unit % srv_buf_pool_chunk_unit_blk_sz == 0);
5239
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 ut_ad(srv_buf_pool_chunk_unit % UNIV_PAGE_SIZE == 0);
5240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 ut_ad(0 ==
5241 srv_buf_pool_size % (srv_buf_pool_chunk_unit * srv_buf_pool_instances));
5242
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 ut_ad(srv_buf_pool_chunk_unit * srv_buf_pool_instances <= srv_buf_pool_size);
5243
5244 9726 srv_buf_pool_curr_size = srv_buf_pool_size;
5245
5246 /* Do not enable backoff algorithm for small buffer pool. */
5247
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9724 times.
9726 if (!innodb_empty_free_list_algorithm_allowed(
5248 static_cast<srv_empty_free_list_t>(srv_empty_free_list_algorithm))) {
5249 2 sql_print_information(
5250 "InnoDB: innodb_empty_free_list_algorithm has been changed to legacy "
5251 "because of small buffer pool size. In order to use backoff, "
5252 "increase buffer pool at least up to 20MB.\n");
5253 2 srv_empty_free_list_algorithm = SRV_EMPTY_FREE_LIST_LEGACY;
5254 }
5255 9726 }
5256
5257 template <size_t N>
5258 58356 static bool innodb_variable_is_set(const char (&var_name)[N]) {
5259 enum enum_variable_source source;
5260
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29178 times.
58356 ut_a(sysvar_source_svc != nullptr);
5261
1/2
✓ Branch 0 taken 29178 times.
✗ Branch 1 not taken.
58356 const auto svc_result = sysvar_source_svc->get(var_name, N - 1, &source);
5262
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29178 times.
58356 ut_a(!svc_result);
5263 58356 return source != COMPILED;
5264 }
5265
5266 9726 static bool innodb_redo_log_capacity_is_set() {
5267 9726 return innodb_variable_is_set("innodb_redo_log_capacity");
5268 }
5269
5270 9726 bool innodb_log_file_size_is_set() {
5271 9726 return innodb_variable_is_set("innodb_log_file_size");
5272 }
5273
5274 9726 bool innodb_log_n_files_is_set() {
5275 9726 return innodb_variable_is_set("innodb_log_files_in_group");
5276 }
5277
5278 /** Initialize srv_redo_log_capacity / srv_redo_log_capacity_used. */
5279 9726 static void innodb_redo_log_capacity_init() {
5280
1/2
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
9726 DBUG_TRACE;
5281
5282
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 ut_a(MB % UNIV_PAGE_SIZE == 0);
5283
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 ut_a(srv_redo_log_capacity % MB == 0);
5284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 ut_a(srv_redo_log_capacity > 0);
5285
5286 9726 srv_redo_log_capacity_used = srv_redo_log_capacity;
5287
5288
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 if (sysvar_source_svc == nullptr) {
5289 return;
5290 }
5291
5292
1/2
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
9726 const bool file_size_set = innodb_log_file_size_is_set();
5293
5294
1/2
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
9726 const bool n_files_set = innodb_log_n_files_is_set();
5295
5296
1/2
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
9726 bool capacity_set = innodb_redo_log_capacity_is_set();
5297
5298
2/2
✓ Branch 0 taken 9513 times.
✓ Branch 1 taken 213 times.
9726 if (capacity_set) {
5299
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 9486 times.
9513 if (file_size_set) {
5300
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 ib::warn(ER_IB_MSG_LOG_PARAMS_FILE_SIZE_UNUSED);
5301 }
5302
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9511 times.
9513 if (n_files_set) {
5303
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 ib::warn(ER_IB_MSG_LOG_PARAMS_N_FILES_UNUSED);
5304 }
5305 } else {
5306
4/4
✓ Branch 0 taken 210 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 208 times.
213 if (file_size_set || n_files_set) {
5307 5 srv_redo_log_capacity_used = srv_log_file_size * srv_log_n_files;
5308 5 capacity_set = true; // do not change it in dedicated_server mode
5309
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 ib::warn(ER_IB_MSG_LOG_PARAMS_LEGACY_USAGE, srv_redo_log_capacity_used);
5310 }
5311 }
5312
5313
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 if (srv_dedicated_server) {
5314 double auto_buf_pool_size_in_gb;
5315 static const char *var_name_buf_pool_size = "innodb_buffer_pool_size";
5316 enum enum_variable_source source;
5317
5318 auto_buf_pool_size_in_gb = static_cast<double>(srv_buf_pool_size / GB);
5319
5320 /* If user has set buffer pool size in .cnf, we will not use it as base
5321 line for log_file_size auto tuning, instead, we will get the value of
5322 possible tuned buffer pool size. */
5323 if (!sysvar_source_svc->get(
5324 var_name_buf_pool_size,
5325 static_cast<unsigned int>(strlen(var_name_buf_pool_size)),
5326 &source)) {
5327 if (source != COMPILED) {
5328 double server_mem = get_sys_mem();
5329
5330 #ifdef UNIV_DEBUG_DEDICATED
5331 server_mem = srv_debug_system_mem_size / GB;
5332 #endif /* UNIV_DEBUG_DEDICATED */
5333
5334 if (server_mem < 1.0) {
5335 ;
5336 } else if (server_mem <= 4.0) {
5337 auto_buf_pool_size_in_gb = static_cast<double>(server_mem * 0.5);
5338 } else
5339 auto_buf_pool_size_in_gb = static_cast<double>(server_mem * 0.75);
5340 }
5341 }
5342
5343 if (!capacity_set) {
5344 /* We update srv_redo_log_capacity (underlying sysvar variable),
5345 because that is what innodb_dedicated_server is expected to do. */
5346 if (auto_buf_pool_size_in_gb < 1.0) {
5347 ut_ad(srv_redo_log_capacity == 100 * 1024 * 1024);
5348 } else if (auto_buf_pool_size_in_gb < 8.0) {
5349 srv_redo_log_capacity =
5350 static_cast<ulong>(round(auto_buf_pool_size_in_gb)) * 512ULL * MB;
5351 } else if (auto_buf_pool_size_in_gb <= 128.0) {
5352 srv_redo_log_capacity =
5353 static_cast<ulong>(round(auto_buf_pool_size_in_gb * 0.75)) * GB;
5354 } else {
5355 constexpr os_offset_t LOG_CAPACITY_FOR_BIG_DEDICATED_SERVER = 128 * GB;
5356
5357 static_assert(
5358 LOG_CAPACITY_FOR_BIG_DEDICATED_SERVER <= LOG_CAPACITY_MAX,
5359 "Redo log capacity, for the dedicated server, is too big.");
5360
5361 srv_redo_log_capacity = LOG_CAPACITY_FOR_BIG_DEDICATED_SERVER;
5362 }
5363 srv_redo_log_capacity_used = srv_redo_log_capacity;
5364
5365 } else {
5366 ut_a(srv_redo_log_capacity_used % MB == 0);
5367 ib::warn(ER_IB_MSG_LOG_PARAMS_DEDICATED_SERVER_IGNORED,
5368 ulonglong{srv_redo_log_capacity_used / MB});
5369 }
5370 }
5371
5372
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 ut_a(LOG_CAPACITY_MIN <= srv_redo_log_capacity_used);
5373
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 ut_a(srv_redo_log_capacity_used <= LOG_CAPACITY_MAX);
5374
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 ut_a(srv_redo_log_capacity_used % MB == 0);
5375
1/2
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
9726 }
5376
5377 /** Initialize, validate and normalize the InnoDB startup parameters.
5378 @return failure code
5379 @retval 0 on success
5380 @retval HA_ERR_OUT_OF_MEM when out of memory
5381 @retval HA_ERR_INITIALIZATION when some parameters are out of range */
5382 9733 static int innodb_init_params() {
5383
1/2
✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
9733 DBUG_TRACE;
5384
5385 static char current_dir[3];
5386 char *default_path;
5387
5388 /* First calculate the default path for innodb_data_home_dir etc.,
5389 in case the user has not given any value. */
5390
5391 /* It's better to use current lib, to keep paths short */
5392 9733 current_dir[0] = FN_CURLIB;
5393 9733 current_dir[1] = FN_LIBCHAR;
5394 9733 current_dir[2] = 0;
5395 9733 default_path = current_dir;
5396
5397
1/2
✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
9733 std::string mysqld_datadir{default_path};
5398
5399
1/2
✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
9733 MySQL_datadir_path = Fil_path{mysqld_datadir};
5400
5401 /* Validate, normalize and interpret the InnoDB start-up parameters. */
5402
5403 /* The default dir for data files is the datadir of MySQL */
5404
5405 9733 srv_data_home =
5406
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 50 times.
52 (innobase_data_home_dir == nullptr || *innobase_data_home_dir == '\0')
5407
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 9681 times.
9785 ? default_path
5408 : innobase_data_home_dir;
5409 9733 Fil_path::normalize(srv_data_home);
5410
5411 /* Validate the undo directory. */
5412
3/4
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 9678 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 55 times.
9733 if (srv_undo_dir == nullptr || srv_undo_dir[0] == 0) {
5413 9678 srv_undo_dir = default_path;
5414 } else {
5415 55 Fil_path::normalize(srv_undo_dir);
5416 }
5417
5418
1/2
✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
9733 MySQL_undo_path = Fil_path{srv_undo_dir};
5419
5420
4/6
✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9733 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 9732 times.
9733 if (MySQL_undo_path.is_ancestor(default_path)) {
5421
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 log_errlog(ERROR_LEVEL, ER_INNODB_INVALID_INNODB_UNDO_DIRECTORY_LOCATION);
5422 1 return HA_ERR_INITIALIZATION;
5423 }
5424
5425 /* Validate the temp directory */
5426
2/2
✓ Branch 0 taken 9725 times.
✓ Branch 1 taken 7 times.
9732 if (ibt::srv_temp_dir == nullptr) {
5427 9725 ibt::srv_temp_dir = default_path;
5428 } else {
5429 os_file_type_t type;
5430 bool exists;
5431
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 os_file_status(ibt::srv_temp_dir, &exists, &type);
5432
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
7 if (!exists || type != OS_FILE_TYPE_DIR) {
5433
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
6 ib::error(ER_IB_ERR_TEMP_TABLESPACE_DIR_DOESNT_EXIST)
5434
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 << "Invalid innodb_temp_tablespaces_dir: " << ibt::srv_temp_dir
5435
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 << ". Directory doesn't exist or not valid";
5436 5 return HA_ERR_INITIALIZATION;
5437 }
5438
5439
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 Fil_path temp_dir(ibt::srv_temp_dir);
5440
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (temp_dir.path().empty()) {
5441 ib::error(ER_IB_ERR_TEMP_TABLESPACE_DIR_EMPTY)
5442 << "Invalid innodb_temp_tablespaces dir: " << ibt::srv_temp_dir
5443 << ". Path cannot be empty";
5444 return HA_ERR_INITIALIZATION;
5445 }
5446
5447
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (strchr(ibt::srv_temp_dir, ';')) {
5448 ib::error(ER_IB_ERR_TEMP_TABLESPACE_DIR_CONTAINS_SEMICOLON)
5449 << "Invalid innodb_temp_tablespaces dir: " << ibt::srv_temp_dir
5450 << ". Path cannot contain ;";
5451 return HA_ERR_INITIALIZATION;
5452 }
5453
5454
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (MySQL_datadir_path.is_ancestor(
5455
3/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
8 Fil_path::get_real_path(temp_dir.path()))) {
5456
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 ib::error(ER_IB_ERR_TEMP_TABLESPACE_DIR_SUBDIR_OF_DATADIR)
5457
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 << "Invalid innodb_temp_tablespaces_dir=" << ibt::srv_temp_dir
5458
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 << ". This path should not be a subdirectory of the datadir.";
5459 2 return HA_ERR_INITIALIZATION;
5460 }
5461
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 }
5462
5463 9727 Fil_path::normalize(ibt::srv_temp_dir);
5464
5465 /* The default dir for log files is the datadir of MySQL */
5466
5467
2/2
✓ Branch 0 taken 9713 times.
✓ Branch 1 taken 14 times.
9727 if (srv_log_group_home_dir == nullptr) {
5468 9713 srv_log_group_home_dir = default_path;
5469 }
5470 9727 Fil_path::normalize(srv_log_group_home_dir);
5471
5472
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9726 times.
9727 if (strchr(srv_log_group_home_dir, ';')) {
5473
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 log_errlog(ERROR_LEVEL, ER_INNODB_INVALID_LOG_GROUP_HOME_DIR);
5474 1 return HA_ERR_INITIALIZATION;
5475 }
5476
5477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 if (strchr(srv_undo_dir, ';')) {
5478 log_errlog(ERROR_LEVEL, ER_INNODB_INVALID_INNODB_UNDO_DIRECTORY);
5479 return HA_ERR_INITIALIZATION;
5480 }
5481
5482 if (!is_filename_allowed(srv_buf_dump_filename, strlen(srv_buf_dump_filename),
5483 false)) {
5484 log_errlog(ERROR_LEVEL, ER_INNODB_ILLEGAL_COLON_IN_POOL);
5485 return HA_ERR_INITIALIZATION;
5486 }
5487
5488 /* Check that the value of system variable innodb_page_size was
5489 set correctly. Its value was put into srv_page_size. If valid,
5490 return the associated srv_page_size_shift. */
5491 9726 srv_page_size_shift = page_size_validate(srv_page_size);
5492
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 if (!srv_page_size_shift) {
5493 log_errlog(ERROR_LEVEL, ER_INNODB_INVALID_PAGE_SIZE, srv_page_size);
5494 return HA_ERR_INITIALIZATION;
5495 }
5496
5497
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 ut_a(srv_log_buffer_size % OS_FILE_LOG_BLOCK_SIZE == 0);
5498
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 ut_a(srv_log_buffer_size > 0);
5499
5500
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 ut_a(srv_log_write_ahead_size % OS_FILE_LOG_BLOCK_SIZE == 0);
5501
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 ut_a(srv_log_write_ahead_size > 0);
5502
5503
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 assert(innodb_change_buffering <= IBUF_USE_ALL);
5504
5505 /* Check that interdependent parameters have sane values. */
5506
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 if (srv_max_buf_pool_modified_pct < srv_max_dirty_pages_pct_lwm) {
5507 log_errlog(WARNING_LEVEL, ER_INNODB_DIRTY_WATER_MARK_NOT_LOW,
5508 srv_max_buf_pool_modified_pct);
5509 srv_max_dirty_pages_pct_lwm = srv_max_buf_pool_modified_pct;
5510 }
5511
5512
1/2
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
9726 if (srv_max_io_capacity == SRV_MAX_IO_CAPACITY_DUMMY_DEFAULT) {
5513
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 if (srv_io_capacity >= SRV_MAX_IO_CAPACITY_LIMIT / 2) {
5514 /* Avoid overflow. */
5515 srv_max_io_capacity = SRV_MAX_IO_CAPACITY_LIMIT;
5516 } else {
5517 /* The user has not set the value. We should
5518 set it based on innodb_io_capacity. */
5519 9726 srv_max_io_capacity = std::max(2 * srv_io_capacity, 2000UL);
5520 }
5521
5522 } else if (srv_max_io_capacity < srv_io_capacity) {
5523 log_errlog(WARNING_LEVEL, ER_INNODB_IO_CAPACITY_EXCEEDS_MAX,
5524 srv_max_io_capacity);
5525 srv_io_capacity = srv_max_io_capacity;
5526 }
5527
5528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 if (UNIV_PAGE_SIZE_DEF != srv_page_size) {
5529 ib::warn(ER_IB_MSG_538)
5530 << "innodb-page-size has been changed from the"
5531 " default value "
5532 << UNIV_PAGE_SIZE_DEF << " to " << srv_page_size << ".";
5533 }
5534
5535
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 if (srv_log_write_ahead_size > srv_page_size) {
5536 srv_log_write_ahead_size = srv_page_size;
5537 } else {
5538 9726 ulong srv_log_write_ahead_size_tmp = OS_FILE_LOG_BLOCK_SIZE;
5539
5540
2/2
✓ Branch 0 taken 38904 times.
✓ Branch 1 taken 9726 times.
48630 while (srv_log_write_ahead_size_tmp < srv_log_write_ahead_size) {
5541 38904 srv_log_write_ahead_size_tmp = srv_log_write_ahead_size_tmp * 2;
5542 }
5543
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 if (srv_log_write_ahead_size_tmp != srv_log_write_ahead_size) {
5544 srv_log_write_ahead_size = srv_log_write_ahead_size_tmp / 2;
5545 }
5546 }
5547
5548 9726 srv_buf_pool_size = srv_buf_pool_curr_size;
5549
5550 9726 innodb_log_checksums_func_update(srv_log_checksums);
5551
5552 #ifdef HAVE_LINUX_LARGE_PAGES
5553
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 if ((os_use_large_pages = opt_large_pages)) {
5554 os_large_page_size = opt_large_page_size;
5555 }
5556 #endif /* HAVE_LINUX_LARGE_PAGES */
5557
5558 9726 row_rollback_on_timeout = innobase_rollback_on_timeout;
5559
5560
2/2
✓ Branch 0 taken 9723 times.
✓ Branch 1 taken 3 times.
9726 if (innobase_open_files < 10) {
5561 9723 innobase_open_files = 300;
5562
4/4
✓ Branch 0 taken 9700 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 9697 times.
✓ Branch 3 taken 3 times.
9723 if (srv_file_per_table && table_cache_size > 300) {
5563 9697 innobase_open_files = table_cache_size;
5564 }
5565 }
5566
5567
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9725 times.
9726 if (innobase_open_files > (long)open_files_limit) {
5568
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
2 ib::warn(ER_IB_MSG_539) << "innodb_open_files should not be greater"
5569
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 " than the open_files_limit.\n";
5570
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (innobase_open_files > (long)table_cache_size) {
5571 1 innobase_open_files = table_cache_size;
5572 }
5573 }
5574
5575 9726 srv_innodb_status = innobase_create_status_file;
5576
5577 /* Round up ddl:fts_parser_threads to nearest power of 2 number */
5578 {
5579 9726 ulong n_parser_threads = 1;
5580
5581
2/2
✓ Branch 0 taken 9726 times.
✓ Branch 1 taken 9726 times.
19452 while (n_parser_threads < ddl::fts_parser_threads) {
5582 9726 n_parser_threads <<= 1;
5583 }
5584
5585 9726 ddl::fts_parser_threads = n_parser_threads;
5586 }
5587
5588 /* Store the default charset-collation number of this MySQL
5589 installation */
5590
5591 9726 data_mysql_default_charset_coll = (ulint)default_charset_info->number;
5592
5593 9726 innobase_commit_concurrency_init_default();
5594
5595
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 9713 times.
9726 if (srv_force_recovery == SRV_FORCE_NO_LOG_REDO) {
5596 13 srv_read_only_mode = true;
5597 }
5598
5599 9726 high_level_read_only =
5600
4/4
✓ Branch 0 taken 9671 times.
✓ Branch 1 taken 55 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 9666 times.
9726 srv_read_only_mode || srv_force_recovery > SRV_FORCE_NO_TRX_UNDO;
5601
5602
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 9671 times.
9726 if (srv_read_only_mode) {
5603
2/4
✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 55 times.
✗ Branch 3 not taken.
55 ib::info(ER_IB_MSG_540) << "Started in read only mode";
5604
5605 /* There is no write except to intrinsic table and so turn-off
5606 doublewrite mechanism completely. */
5607 55 dblwr::g_mode = dblwr::Mode::OFF;
5608 }
5609
5610 #ifdef LINUX_NATIVE_AIO
5611
1/2
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
9726 if (srv_use_native_aio) {
5612
2/4
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9726 times.
✗ Branch 3 not taken.
9726 ib::info(ER_IB_MSG_541) << "Using Linux native AIO";
5613 }
5614 #elif !defined _WIN32
5615 /* Currently native AIO is supported only on Windows and Linux
5616 and that also when the support is compiled in. In all other
5617 cases, we ignore the setting of innodb_use_native_aio. */
5618 srv_use_native_aio = false;
5619 #endif
5620
5621 #ifndef _WIN32
5622 /* Check if innodb_dedicated_server == ON and O_DIRECT is supported */
5623
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 9726 times.
9726 if (srv_dedicated_server && sysvar_source_svc != nullptr &&
5624 os_is_o_direct_supported()) {
5625 static const char *variable_name = "innodb_flush_method";
5626 enum enum_variable_source source;
5627
5628 if (!sysvar_source_svc->get(variable_name, strlen(variable_name),
5629 &source)) {
5630 /* If innodb_flush_method is not specified explicitly */
5631 if (source == COMPILED) {
5632 innodb_flush_method = static_cast<ulong>(SRV_UNIX_O_DIRECT_NO_FSYNC);
5633 } else {
5634 ib::warn(ER_IB_MSG_542)
5635 << "Option innodb_dedicated_server"
5636 " is ignored for innodb_flush_method"
5637 "because innodb_flush_method="
5638 << innodb_flush_method_names[innodb_flush_method]
5639 << " is specified explicitly.";
5640 }
5641 }
5642 }
5643
5644 9726 srv_unix_file_flush_method =
5645 9726 static_cast<srv_unix_flush_t>(innodb_flush_method);
5646
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 ut_ad(innodb_flush_method <= SRV_UNIX_O_DIRECT_NO_FSYNC);
5647 #else
5648 srv_win_file_flush_method = static_cast<srv_win_flush_t>(innodb_flush_method);
5649 ut_ad(innodb_flush_method <= SRV_WIN_IO_NORMAL);
5650 if (srv_use_native_aio) {
5651 ib::info(ER_IB_MSG_541) << "Using Windows native AIO";
5652 }
5653 #endif /* !_WIN32 */
5654
5655 #ifdef WITH_WSREP
5656
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 if (innobase_disallow_writes) {
5657 ib::warn() << "innodb_disallow_writes has been deprecated and"
5658 " will be removed in future release."
5659 " Consider using read_only instead.";
5660 }
5661 #endif /* WITH_WSREP */
5662
5663 /* Set the maximum number of threads which can wait for a semaphore
5664 inside InnoDB: this is the 'sync wait array' size, as well as the
5665 maximum number of threads that can wait in the 'srv_conc array' for
5666 their time to enter InnoDB. */
5667 9726 srv_max_n_threads = 100 * 1024;
5668
5669 /* This is the first time univ_page_size is used.
5670 It was initialized to 16k pages before srv_page_size was set */
5671
2/4
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9726 times.
✗ Branch 3 not taken.
9726 univ_page_size.copy_from(page_size_t(srv_page_size, srv_page_size, false));
5672
5673
1/2
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
9726 srv_sys_space.set_space_id(TRX_SYS_SPACE);
5674
5675 /* Create the filespace flags. */
5676
1/2
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
9726 predefined_flags = fsp_flags_init(univ_page_size, false, false, true, false);
5677 9726 fsp_flags_set_sdi(predefined_flags);
5678
5679
1/2
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
9726 srv_sys_space.set_flags(predefined_flags);
5680
5681
1/2
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
9726 srv_sys_space.set_name(dict_sys_t::s_sys_space_name);
5682
1/2
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
9726 srv_sys_space.set_path(srv_data_home);
5683
5684 /* We set the temporary tablspace id later, after recovery.
5685 The temp tablespace doesn't support raw devices.
5686 Set the name and path. */
5687
1/2
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
9726 srv_tmp_space.set_name(dict_sys_t::s_temp_space_name);
5688
1/2
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
9726 srv_tmp_space.set_path(srv_data_home);
5689
5690 /* Create the filespace flags with the temp flag set. */
5691 uint32_t fsp_flags =
5692
1/2
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
9726 fsp_flags_init(univ_page_size, false, false, false, true);
5693
1/2
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
9726 srv_tmp_space.set_flags(fsp_flags);
5694
5695 /* Set buffer pool size to default for fast startup when mysqld is
5696 run with --help --verbose options. */
5697 9726 ulint srv_buf_pool_size_org = 0;
5698
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
9726 if (opt_help && opt_verbose && opt_validate_config &&
5699 srv_buf_pool_size > srv_buf_pool_def_size) {
5700 ib::warn(ER_IB_MSG_543) << "Setting innodb_buf_pool_size to "
5701 << srv_buf_pool_def_size << " for fast startup, "
5702 << "when running with --help --verbose options.";
5703 srv_buf_pool_size_org = srv_buf_pool_size;
5704 srv_buf_pool_size = srv_buf_pool_def_size;
5705 }
5706
5707
1/2
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
9726 innodb_buffer_pool_size_init();
5708
5709
1/2
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
9726 innodb_undo_tablespaces_deprecate();
5710
1/2
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
9726 innodb_parallel_doublewrite_path_deprecate();
5711
1/2
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
9726 innodb_parallel_dblwr_encrypt_deprecate();
5712
5713
1/2
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
9726 innodb_redo_log_capacity_init();
5714
5715 /* Set the original value back to show in help. */
5716
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
9726 if (srv_buf_pool_size_org != 0) {
5717 srv_buf_pool_size_org = buf_pool_size_align(srv_buf_pool_size_org);
5718 srv_buf_pool_curr_size = srv_buf_pool_size_org;
5719 }
5720
5721
2/2
✓ Branch 0 taken 9713 times.
✓ Branch 1 taken 13 times.
9726 if (srv_n_page_cleaners > srv_buf_pool_instances) {
5722 /* limit of page_cleaner parallelizability
5723 is number of buffer pool instances. */
5724 9713 srv_n_page_cleaners = srv_buf_pool_instances;
5725 }
5726
5727 9726 srv_lock_table_size = 5 * (srv_buf_pool_size / UNIV_PAGE_SIZE);
5728
5729 9726 return 0;
5730 9733 }
5731
5732 9693 long innobase_get_open_files_limit() { return innobase_open_files; }
5733 12 void innobase_set_open_files_limit(long new_limit) {
5734 12 innobase_open_files = new_limit;
5735 12 }
5736
5737 /** Perform post-commit/rollback cleanup after DDL statement
5738 @param[in,out] thd connection thread */
5739 327376 static void innobase_post_ddl(THD *thd) {
5740 /* During upgrade, etc., the log_ddl may haven't been
5741 initialized and there is nothing to do now. */
5742
2/2
✓ Branch 0 taken 317754 times.
✓ Branch 1 taken 9622 times.
327376 if (log_ddl != nullptr) {
5743
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 317755 times.
317754 DBUG_EXECUTE_IF("DDL_Log_remove_inject_startup_error_3",
5744 srv_inject_too_many_concurrent_trxs = true;);
5745
5746 317755 dberr_t err = log_ddl->post_ddl(thd);
5747
5748 /* If this fails, do not continue startup. */
5749
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 317665 times.
317665 if (err != DB_SUCCESS) {
5750 ib::fatal(UT_LOCATION_HERE, ER_IB_MSG_DDL_LOG_FAIL_POST_DDL);
5751 }
5752 }
5753 327287 }
5754
5755 /** Initialize the InnoDB storage engine plugin.
5756 @param[in,out] p InnoDB handlerton
5757 @return error code
5758 @retval 0 on success */
5759 9734 static int innodb_init(void *p) {
5760
1/2
✓ Branch 0 taken 9734 times.
✗ Branch 1 not taken.
9734 DBUG_TRACE;
5761
5762
1/2
✓ Branch 0 taken 9734 times.
✗ Branch 1 not taken.
9734 acquire_plugin_services();
5763
5764 9734 handlerton *innobase_hton = (handlerton *)p;
5765 9734 innodb_hton_ptr = innobase_hton;
5766
5767 9734 innobase_hton->state = SHOW_OPTION_YES;
5768 9734 innobase_hton->db_type = DB_TYPE_INNODB;
5769 9734 innobase_hton->savepoint_offset = sizeof(trx_named_savept_t);
5770 9734 innobase_hton->close_connection = innobase_close_connection;
5771 9734 innobase_hton->kill_connection = innobase_kill_connection;
5772 9734 innobase_hton->savepoint_set = innobase_savepoint;
5773 9734 innobase_hton->savepoint_rollback = innobase_rollback_to_savepoint;
5774
5775 9734 innobase_hton->savepoint_rollback_can_release_mdl =
5776 innobase_rollback_to_savepoint_can_release_mdl;
5777
5778 9734 innobase_hton->savepoint_release = innobase_release_savepoint;
5779 9734 innobase_hton->commit = innobase_commit;
5780 9734 innobase_hton->rollback = innobase_rollback;
5781 9734 innobase_hton->prepare = innobase_xa_prepare;
5782 9734 innobase_hton->recover = innobase_xa_recover;
5783 9734 innobase_hton->recover_prepared_in_tc = innobase_xa_recover_prepared_in_tc;
5784 9734 innobase_hton->commit_by_xid = innobase_commit_by_xid;
5785 9734 innobase_hton->rollback_by_xid = innobase_rollback_by_xid;
5786 9734 innobase_hton->set_prepared_in_tc = innobase_set_prepared_in_tc;
5787 9734 innobase_hton->set_prepared_in_tc_by_xid = innobase_set_prepared_in_tc_by_xid;
5788 9734 innobase_hton->create = innobase_create_handler;
5789 9734 innobase_hton->is_valid_tablespace_name = innobase_is_valid_tablespace_name;
5790 9734 innobase_hton->alter_tablespace = innobase_alter_tablespace;
5791 9734 innobase_hton->get_tablespace_filename_ext =
5792 innobase_get_tablespace_filename_ext;
5793 9734 innobase_hton->upgrade_tablespace = dd_upgrade_tablespace;
5794 9734 innobase_hton->upgrade_space_version = upgrade_space_version;
5795 9734 innobase_hton->upgrade_logs = dd_upgrade_logs;
5796 9734 innobase_hton->finish_upgrade = dd_upgrade_finish;
5797 9734 innobase_hton->pre_dd_shutdown = innodb_pre_dd_shutdown;
5798 9734 innobase_hton->panic = innodb_shutdown;
5799 9734 innobase_hton->partition_flags = innobase_partition_flags;
5800
5801 9734 innobase_hton->start_consistent_snapshot =
5802 innobase_start_trx_and_assign_read_view;
5803 9734 innobase_hton->clone_consistent_snapshot =
5804 innobase_start_trx_and_clone_read_view;
5805
5806 9734 innobase_hton->store_binlog_info = innobase_store_binlog_info;
5807
5808 9734 innobase_hton->flush_logs = innobase_flush_logs;
5809 9734 innobase_hton->show_status = innobase_show_status;
5810 9734 innobase_hton->lock_hton_log = innobase_lock_hton_log;
5811 9734 innobase_hton->unlock_hton_log = innobase_unlock_hton_log;
5812 9734 innobase_hton->collect_hton_log_info = innobase_collect_hton_log_info;
5813 9734 innobase_hton->fill_is_table = innobase_fill_i_s_table;
5814 9734 innobase_hton->flags = HTON_SUPPORTS_EXTENDED_KEYS |
5815 HTON_SUPPORTS_FOREIGN_KEYS | HTON_SUPPORTS_ATOMIC_DDL |
5816 HTON_CAN_RECREATE | HTON_SUPPORTS_SECONDARY_ENGINE |
5817 HTON_SUPPORTS_TABLE_ENCRYPTION |
5818 HTON_SUPPORTS_ONLINE_BACKUPS | HTON_SUPPORTS_COMPRESSED_COLUMNS |
5819 HTON_SUPPORTS_GENERATED_INVISIBLE_PK;
5820 #ifdef WITH_WSREP
5821 9734 innobase_hton->flags |= HTON_WSREP_REPLICATION;
5822 #endif /* WITH_WSREP */
5823
5824 9734 innobase_hton->replace_native_transaction_in_thd = innodb_replace_trx_in_thd;
5825 9734 innobase_hton->file_extensions = ha_innobase_exts;
5826 9734 innobase_hton->data = &innodb_api_cb;
5827 9734 innobase_hton->ddse_dict_init = innobase_ddse_dict_init;
5828
5829 9734 innobase_hton->dict_register_dd_table_id = innobase_dict_register_dd_table_id;
5830
5831 9734 innobase_hton->dict_cache_reset = innobase_dict_cache_reset;
5832 9734 innobase_hton->dict_cache_reset_tables_and_tablespaces =
5833 innobase_dict_cache_reset_tables_and_tablespaces;
5834
5835 9734 innobase_hton->dict_recover = innobase_dict_recover;
5836 9734 innobase_hton->dict_get_server_version = innobase_dict_get_server_version;
5837 9734 innobase_hton->dict_set_server_version = innobase_dict_set_server_version;
5838
5839 9734 innobase_hton->post_recover = innobase_post_recover;
5840
5841 9734 innobase_hton->is_supported_system_table = innobase_is_supported_system_table;
5842
5843 9734 innobase_hton->get_table_statistics = innobase_get_table_statistics;
5844
5845 9734 innobase_hton->get_index_column_cardinality =
5846 innobase_get_index_column_cardinality;
5847
5848 9734 innobase_hton->get_tablespace_statistics = innobase_get_tablespace_statistics;
5849 9734 innobase_hton->get_tablespace_type = innobase_get_tablespace_type;
5850 9734 innobase_hton->get_tablespace_type_by_name =
5851 innobase_get_tablespace_type_by_name;
5852
5853 9734 innobase_hton->is_tablespace_keyring_pre_v3_encrypted =
5854 innobase_is_tablespace_keyring_pre_v3_encrypted;
5855
5856 9734 innobase_hton->is_dict_readonly = innobase_is_dict_readonly;
5857
5858 9734 innobase_hton->sdi_create = dict_sdi_create;
5859 9734 innobase_hton->sdi_drop = dict_sdi_drop;
5860 9734 innobase_hton->sdi_get_keys = dict_sdi_get_keys;
5861 9734 innobase_hton->sdi_get = dict_sdi_get;
5862 9734 innobase_hton->sdi_set = dict_sdi_set;
5863 9734 innobase_hton->sdi_delete = dict_sdi_delete;
5864
5865 9734 innobase_hton->rotate_encryption_master_key =
5866 innobase_encryption_key_rotation;
5867
5868 9734 innobase_hton->fix_tablespaces_empty_uuid =
5869 innobase_fix_tablespaces_empty_uuid;
5870
5871 9734 innobase_hton->fix_default_table_encryption =
5872 innobase_fix_default_table_encryption;
5873
5874 9734 innobase_hton->redo_log_set_state = innobase_redo_set_state;
5875
5876 9734 innobase_hton->post_ddl = innobase_post_ddl;
5877
5878 #ifdef WITH_WSREP
5879 9734 innobase_hton->wsrep_abort_transaction = wsrep_abort_transaction_func;
5880 9734 innobase_hton->wsrep_set_checkpoint = innobase_wsrep_set_checkpoint;
5881 9734 innobase_hton->wsrep_get_checkpoint = innobase_wsrep_get_checkpoint;
5882
5883 9734 bool wsrep_provider_loaded =
5884
3/4
✓ Branch 0 taken 9734 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 453 times.
✓ Branch 3 taken 9281 times.
9734 !(strlen(wsrep_provider) == 0 || !strcmp(wsrep_provider, WSREP_NONE));
5885
5886 /* innodb_autoinc_lock_mode (recommended value = Interleaved/2) */
5887
2/2
✓ Branch 0 taken 453 times.
✓ Branch 1 taken 9281 times.
9734 if (wsrep_provider_loaded &&
5888
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 452 times.
453 innobase_autoinc_lock_mode != AUTOINC_NO_LOCKING) {
5889
1/3
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 switch (pxc_strict_mode) {
5890 case PXC_STRICT_MODE_DISABLED:
5891 break;
5892 case PXC_STRICT_MODE_PERMISSIVE:
5893 WSREP_WARN(
5894 "Percona-XtraDB-Cluster doesn't recommend"
5895 " setting innodb_autoinc_lock_mode to"
5896 " TRADITIONAL/CONSECUTIVE"
5897 " with pxc_strict_mode = PERMISSIVE");
5898 break;
5899 1 case PXC_STRICT_MODE_ENFORCING:
5900 case PXC_STRICT_MODE_MASTER:
5901 default:
5902
14/28
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 1 times.
✗ Branch 27 not taken.
1 WSREP_ERROR(
5903 "Percona-XtraDB-Cluster prohibits"
5904 " setting innodb_autoinc_lock_mode to"
5905 " TRADITIONAL/CONSECUTIVE"
5906 " with pxc_strict_mode = ENFORCING"
5907 " or MASTER");
5908
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 return (innodb_init_abort());
5909 break;
5910 }
5911 }
5912 #endif /* WITH_WSREP */
5913
5914 /* Initialize handler clone interfaces for. */
5915
5916 9733 innobase_hton->clone_interface.clone_capability = innodb_clone_get_capability;
5917 9733 innobase_hton->clone_interface.clone_begin = innodb_clone_begin;
5918 9733 innobase_hton->clone_interface.clone_copy = innodb_clone_copy;
5919 9733 innobase_hton->clone_interface.clone_ack = innodb_clone_ack;
5920 9733 innobase_hton->clone_interface.clone_end = innodb_clone_end;
5921
5922 9733 innobase_hton->clone_interface.clone_apply_begin = innodb_clone_apply_begin;
5923 9733 innobase_hton->clone_interface.clone_apply = innodb_clone_apply;
5924 9733 innobase_hton->clone_interface.clone_apply_end = innodb_clone_apply_end;
5925
5926 9733 innobase_hton->foreign_keys_flags =
5927 HTON_FKS_WITH_PREFIX_PARENT_KEYS |
5928 HTON_FKS_NEED_DIFFERENT_PARENT_AND_SUPPORTING_KEYS |
5929 HTON_FKS_WITH_EXTENDED_PARENT_KEYS;
5930
5931 9733 innobase_hton->check_fk_column_compat = innodb_check_fk_column_compat;
5932 9733 innobase_hton->fk_name_suffix = {STRING_WITH_LEN("_ibfk_")};
5933
5934 9733 innobase_hton->is_reserved_db_name = innobase_check_reserved_file_name;
5935
5936 9733 innobase_hton->page_track.start = innobase_page_track_start;
5937 9733 innobase_hton->page_track.stop = innobase_page_track_stop;
5938 9733 innobase_hton->page_track.purge = innobase_page_track_purge;
5939 9733 innobase_hton->page_track.get_page_ids = innobase_page_track_get_page_ids;
5940 9733 innobase_hton->page_track.get_num_page_ids =
5941 innobase_page_track_get_num_page_ids;
5942 9733 innobase_hton->page_track.get_status = innobase_page_track_get_status;
5943
5944 9733 innobase_hton->upgrade_get_compression_dict_data =
5945 dd_upgrade_get_compression_dict_data;
5946
5947 static_assert(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR);
5948
5949
1/2
✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
9733 os_file_set_umask(my_umask);
5950
5951 /* Setup the memory alloc/free tracing mechanisms before calling
5952 any functions that could possibly allocate memory. */
5953
1/2
✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
9733 ut_new_boot();
5954
5955 #ifdef HAVE_PSI_INTERFACE
5956 /* Register keys with MySQL performance schema */
5957 int count;
5958
5959 #ifdef UNIV_DEBUG
5960 /** Count of Performance Schema keys that have been registered. */
5961 9733 int global_count = 0;
5962 #endif /* UNIV_DEBUG */
5963
5964 9733 count = static_cast<int>(array_elements(all_pthread_mutexes));
5965
1/2
✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
9733 mysql_mutex_register("innodb", all_pthread_mutexes, count);
5966
5967 #ifdef UNIV_DEBUG
5968 9733 global_count += count;
5969 #endif /* UNIV_DEBUG */
5970
5971 #ifdef UNIV_PFS_MEMORY
5972 9733 count = static_cast<int>(array_elements(pfs_instrumented_innodb_memory));
5973
1/2
✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
9733 mysql_memory_register("innodb", pfs_instrumented_innodb_memory, count);
5974 #endif /* UNIV_PFS_MEMORY */
5975
5976 #ifdef UNIV_PFS_MUTEX
5977 9733 count = static_cast<int>(array_elements(all_innodb_mutexes));
5978
1/2
✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
9733 mysql_mutex_register("innodb", all_innodb_mutexes, count);
5979
5980 #ifdef UNIV_DEBUG
5981 9733 global_count += count;
5982 #endif /* UNIV_DEBUG */
5983
5984 #endif /* UNIV_PFS_MUTEX */
5985
5986 #ifdef UNIV_PFS_RWLOCK
5987 9733 count = static_cast<int>(array_elements(all_innodb_rwlocks));
5988
1/2
✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
9733 mysql_rwlock_register("innodb", all_innodb_rwlocks, count);
5989
5990 #ifdef UNIV_DEBUG
5991 9733 global_count += count;
5992 #endif /* UNIV_DEBUG */
5993
5994 #endif /* UNIV_PFS_MUTEX */
5995
5996 #ifdef UNIV_PFS_THREAD
5997 9733 count = static_cast<int>(array_elements(all_innodb_threads));
5998
1/2
✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
9733 mysql_thread_register("innodb", all_innodb_threads, count);
5999
6000 #ifdef UNIV_DEBUG
6001 9733 global_count += count;
6002 #endif /* UNIV_DEBUG */
6003
6004 #endif /* UNIV_PFS_THREAD */
6005
6006 #ifdef UNIV_PFS_IO
6007 9733 count = static_cast<int>(array_elements(all_innodb_files));
6008
1/2
✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
9733 mysql_file_register("innodb", all_innodb_files, count);
6009
6010 #ifdef UNIV_DEBUG
6011 9733 global_count += count;
6012 #endif /* UNIV_DEBUG */
6013
6014 #endif /* UNIV_PFS_IO */
6015
6016 9733 count = static_cast<int>(array_elements(all_innodb_conds));
6017
1/2
✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
9733 mysql_cond_register("innodb", all_innodb_conds, count);
6018
6019 #ifdef UNIV_DEBUG
6020 9733 global_count += count;
6021 #endif /* UNIV_DEBUG */
6022
6023
1/2
✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
9733 mysql_data_lock_register(&innodb_data_lock_inspector);
6024
6025 #ifdef UNIV_DEBUG
6026
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9733 times.
9733 if (mysql_pfs_key_t::get_count() != global_count) {
6027 ib::error(ER_IB_MSG_544) << "You have created new InnoDB PFS key(s) but "
6028 << mysql_pfs_key_t::get_count() - global_count
6029 << " key(s) is/are not registered with PFS. Please"
6030 << " register the keys in PFS arrays in"
6031 << " ha_innodb.cc.";
6032
6033 return HA_ERR_INITIALIZATION;
6034 }
6035 #endif /* UNIV_DEBUG */
6036
6037 #endif /* HAVE_PSI_INTERFACE */
6038
6039
1/2
✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
9733 os_event_global_init();
6040
6041
3/4
✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 9726 times.
9733 if (innodb_init_params()) {
6042
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 return innodb_init_abort();
6043 }
6044
6045 /* After this point, error handling has to use
6046 innodb_init_abort(). */
6047
6048 /* Initialize component service handles */
6049
2/4
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9726 times.
9726 if (innobase::component_services::intitialize_service_handles() == false) {
6050 return innodb_init_abort();
6051 }
6052
6053
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9726 times.
9726 if (srv_default_table_encryption == DEFAULT_TABLE_ENC_ONLINE_TO_KEYRING &&
6054 !Encryption::tablespace_key_exists_or_create_new_one_if_does_not_exist(
6055 FIL_DEFAULT_ENCRYPTION_KEY, server_uuid)) {
6056 sql_print_error(
6057 "InnoDB: cannot enable encryption, innodb_encrypt_tables is set to "
6058 "value different than OFF, but "
6059 "keyring plugin is not available");
6060 return innodb_init_abort();
6061 }
6062
6063 // We are starting encryption threads, we must lock the keyring plugins
6064
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9724 times.
9726 if (srv_n_fil_crypt_threads_requested > 0) {
6065
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 uint number_of_keyring_locked = lock_keyrings(nullptr);
6066
6067
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (number_of_keyring_locked == 0) {
6068 sql_print_error(
6069 "InnoDB: cannot enable encryption threads, "
6070 "keyring plugin is not available");
6071
6072 return innodb_init_abort();
6073 }
6074
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (Encryption::is_keyring_alive() == false) {
6075 sql_print_error(
6076 "InnoDB: keyring plugin is installed but it seems it was not "
6077 "properly initialized. Cannot enable encryption threads.");
6078 unlock_keyrings(nullptr);
6079
6080 return innodb_init_abort();
6081 }
6082 }
6083
6084
2/4
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9726 times.
9726 if (!srv_sys_space.parse_params(innobase_data_file_path, true)) {
6085 ib::error(ER_IB_MSG_545)
6086 << "Unable to parse innodb_data_file_path=" << innobase_data_file_path;
6087 return innodb_init_abort();
6088 }
6089
6090
3/4
✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 9723 times.
9726 if (!srv_tmp_space.parse_params(innobase_temp_data_file_path, false)) {
6091
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 ib::error(ER_IB_MSG_546) << "Unable to parse innodb_temp_data_file_path="
6092
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 << innobase_temp_data_file_path;
6093
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 return innodb_init_abort();
6094 }
6095
6096 /* Perform all sanity check before we take action of deleting files*/
6097
3/4
✓ Branch 0 taken 9723 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 9722 times.
9723 if (srv_sys_space.intersection(&srv_tmp_space)) {
6098
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 log_errlog(ERROR_LEVEL, ER_INNODB_FILES_SAME, srv_tmp_space.name(),
6099 srv_sys_space.name());
6100
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 return innodb_init_abort();
6101 }
6102
6103 /* Check for keyring plugin if UNDO/REDO logs are intended to be encrypted */
6104
6/6
✓ Branch 0 taken 9680 times.
✓ Branch 1 taken 42 times.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 9643 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 9717 times.
9801 if ((srv_undo_log_encrypt || srv_redo_log_encrypt) &&
6105
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 74 times.
79 Encryption::check_keyring() == false) {
6106
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 return innodb_init_abort();
6107 }
6108
6109 9717 return 0;
6110 9734 }
6111
6112 /** De initialize the InnoDB storage engine plugin. */
6113 8361 static int innodb_deinit(MYSQL_PLUGIN plugin_info [[maybe_unused]]) {
6114 8361 release_plugin_services();
6115 8361 return 0;
6116 }
6117
6118 /** Create a hard-coded tablespace file at server initialization.
6119 @param[in] space_id fil_space_t::id
6120 @param[in] filename file name
6121 @param[in] flags tabelspace flags
6122 @retval false on success
6123 @retval true on failure */
6124 283 static bool dd_create_hardcoded(space_id_t space_id, const char *filename,
6125 ulint flags) {
6126 283 page_no_t pages = FIL_IBD_FILE_INITIAL_SIZE;
6127
6128
1/2
✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
283 dberr_t err = fil_ibd_create(space_id, dict_sys_t::s_dd_space_name, filename,
6129 flags, pages, FIL_ENCRYPTION_DEFAULT,
6130 283 KeyringEncryptionKeyIdInfo());
6131
6132
1/2
✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
283 if (err == DB_SUCCESS) {
6133
1/2
✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
283 mtr_t mtr;
6134
1/2
✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
283 mtr.start();
6135
6136
1/2
✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
283 bool ret = fsp_header_init(space_id, pages, &mtr);
6137
6138
1/2
✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
283 mtr.commit();
6139
6140
1/2
✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
283 if (ret) {
6141
1/2
✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
283 btr_sdi_create_index(space_id, false);
6142 283 return (false);
6143 }
6144
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 283 times.
283 }
6145
6146 return (true);
6147 }
6148
6149 /** Open a hard-coded tablespace file at server initialization.
6150 @param[in] space_id fil_space_t::id
6151 @param[in] filename file name
6152 @param[in] flags tabelspace flags
6153 @retval false on success
6154 @retval true on failure */
6155 9339 static bool dd_open_hardcoded(space_id_t space_id, const char *filename,
6156 ulint flags) {
6157 9339 bool fail = false;
6158
1/2
✓ Branch 0 taken 9339 times.
✗ Branch 1 not taken.
9339 fil_space_t *space = fil_space_acquire_silent(space_id);
6159 9339 Keyring_encryption_info keyring_encryption_info;
6160
6161
2/2
✓ Branch 0 taken 1730 times.
✓ Branch 1 taken 7609 times.
9339 if (space != nullptr) {
6162 /* ADD SDI flag presence in predefined flags of mysql
6163 tablespace. */
6164
6165
2/4
✓ Branch 0 taken 1730 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1730 times.
✗ Branch 3 not taken.
3460 if (strstr(space->files.front().name, filename) != nullptr &&
6166 /* Ignore encryption flag as it might have changed */
6167
1/2
✓ Branch 0 taken 1730 times.
✗ Branch 1 not taken.
1730 !((space->flags ^ flags) & ~(FSP_FLAGS_MASK_ENCRYPTION))) {
6168
1/2
✓ Branch 0 taken 1730 times.
✗ Branch 1 not taken.
1730 fil_space_open_if_needed(space);
6169
6170 } else {
6171 fail = true;
6172 }
6173
6174
1/2
✓ Branch 0 taken 1730 times.
✗ Branch 1 not taken.
1730 fil_space_release(space);
6175
6176
1/2
✓ Branch 0 taken 7609 times.
✗ Branch 1 not taken.
7609 } else if (fil_ibd_open(true, FIL_TYPE_TABLESPACE, space_id, flags,
6177 dict_sys_t::s_dd_space_name, filename, true,
6178
1/2
✓ Branch 0 taken 7609 times.
✗ Branch 1 not taken.
7609 false, keyring_encryption_info) == DB_SUCCESS) {
6179 /* Set fil_space_t::size, which is 0 initially. */
6180
1/2
✓ Branch 0 taken 7609 times.
✗ Branch 1 not taken.
7609 ulint size = fil_space_get_size(space_id);
6181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7609 times.
7609 ut_a(size != ULINT_UNDEFINED);
6182
6183 } else {
6184 fail = true;
6185 }
6186
6187
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9339 times.
9339 if (fail) {
6188 my_error(ER_CANT_OPEN_FILE, MYF(0), filename, 0, "");
6189 }
6190
6191 9339 return (fail);
6192 }
6193
6194 /** Open or create InnoDB data files.
6195 @param[in] dict_init_mode whether to create or open the files
6196 @param[in,out] tablespaces predefined tablespaces created by the DDSE
6197 @return 0 on success, 1 on failure */
6198 9707 static int innobase_init_files(dict_init_mode_t dict_init_mode,
6199 List<const Plugin_tablespace> *tablespaces,
6200 bool &is_dd_encrypted) {
6201
1/2
✓ Branch 0 taken 9707 times.
✗ Branch 1 not taken.
9707 DBUG_TRACE;
6202
6203
6/8
✓ Branch 0 taken 9501 times.
✓ Branch 1 taken 206 times.
✓ Branch 2 taken 110 times.
✓ Branch 3 taken 9391 times.
✓ Branch 4 taken 110 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 9707 times.
9707 ut_ad(dict_init_mode == DICT_INIT_CREATE_FILES ||
6204 dict_init_mode == DICT_INIT_CHECK_FILES ||
6205 dict_init_mode == DICT_INIT_UPGRADE_57_FILES);
6206
6207 9707 bool create = (dict_init_mode == DICT_INIT_CREATE_FILES);
6208
6209 /* Check if the data files exist or not. */
6210 dberr_t err =
6211
1/2
✓ Branch 0 taken 9707 times.
✗ Branch 1 not taken.
9707 srv_sys_space.check_file_spec(create, MIN_EXPECTED_TABLESPACE_SIZE);
6212
6213
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 9703 times.
9707 if (err != DB_SUCCESS) {
6214
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 return innodb_init_abort();
6215 }
6216
6217 9703 srv_is_upgrade_mode = (dict_init_mode == DICT_INIT_UPGRADE_57_FILES);
6218
6219 /* Start the InnoDB server. */
6220
1/2
✓ Branch 0 taken 9702 times.
✗ Branch 1 not taken.
9703 err = srv_start(create);
6221
6222
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 9622 times.
9702 if (err != DB_SUCCESS) {
6223
1/2
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
80 return innodb_init_abort();
6224 }
6225
6226 9622 space_id_t upgrade_mysql_plugin_space = SPACE_UNKNOWN;
6227
6228
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 9541 times.
9622 if (srv_is_upgrade_mode) {
6229
2/4
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 81 times.
81 if (!dict_sys_table_id_build()) {
6230 return innodb_init_abort();
6231 }
6232
6233
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
81 if (trx_sys->found_prepared_trx) {
6234 ib::error(ER_DD_UPGRADE_FOUND_PREPARED_XA_TRANSACTION);
6235 return innodb_init_abort();
6236 }
6237
6238 /* Disable AHI when we start loading tables for purge.
6239 These tables are evicted anyway after purge. */
6240
6241 81 bool old_btr_search_value = btr_search_enabled;
6242 81 btr_search_enabled = false;
6243
6244 /* Load all tablespaces upfront from InnoDB Dictionary.
6245 This is needed for applying purge and ibuf from 5.7 */
6246
2/4
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 81 times.
81 if (dict_load_tablespaces_for_upgrade()) {
6247 // there is a keyring v1 encrypted table - fail the upgrade
6248 ib::error(ER_UPGRADE_KEYRING_UNSUPPORTED_VERSION_ENCRYPTION);
6249 return innodb_init_abort();
6250 }
6251
6252 /* Start purge threads immediately and wait for purge to
6253 become empty. All table_ids will be adjusted by a fixed
6254 offset during upgrade. So purge cannot load a table by
6255 table_id later. Also InnoDB dictionary will be dropped
6256 during the process of upgrade. So apply all the purge
6257 now. */
6258
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 srv_start_purge_threads();
6259
6260 uint64_t rseg_history_len;
6261
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 81 times.
170 while ((rseg_history_len = trx_sys->rseg_history_len.load()) != 0) {
6262
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
8 ib::info(ER_IB_MSG_547)
6263
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 << "Waiting for purge to become empty:"
6264
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 << " current purge history len is " << rseg_history_len;
6265
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 sleep(1);
6266 }
6267
6268 81 srv_upgrade_old_undo_found = false;
6269
6270
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 buf_flush_sync_all_buf_pools();
6271
6272 /* We have to find the space_id of "mysql/plugin" here. i.e. before we evict
6273 the tables from cache. */
6274
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 dict_table_t *table = dict_table_open_on_name("mysql/plugin", false, true,
6275 DICT_ERR_IGNORE_NONE);
6276
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 if (table != nullptr) {
6277 81 upgrade_mysql_plugin_space = table->space;
6278
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 dict_table_close(table, false, false);
6279 }
6280
6281
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 dict_upgrade_evict_tables_cache();
6282
6283
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 dict_stats_evict_tablespaces();
6284
6285 81 btr_search_enabled = old_btr_search_value;
6286 }
6287
6288 9622 bool do_encrypt = false;
6289
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 bool ret = dict_detect_encryption_of_mysql_ibd(
6290 dict_init_mode, upgrade_mysql_plugin_space, do_encrypt);
6291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9622 times.
9622 if (!ret) {
6292 ib::error(ER_XB_MSG_4, "mysql.ibd")
6293 << "Failed to determine if mysql.ibd is encrypted. "
6294 "Have you deleted it?";
6295 return innodb_init_abort();
6296 }
6297
6298
4/6
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 9602 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 9622 times.
9622 if (do_encrypt && !Encryption::check_keyring()) {
6299 my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0));
6300 return innodb_init_abort();
6301 }
6302
6303 9622 is_dd_encrypted = do_encrypt;
6304
6305 9622 const ulint dd_space_flags =
6306
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 9602 times.
9622 do_encrypt ? predefined_flags | FSP_FLAGS_MASK_ENCRYPTION
6307 : predefined_flags;
6308
6309 // For upgrade from 5.7, create mysql.ibd
6310 9622 create |= (dict_init_mode == DICT_INIT_UPGRADE_57_FILES);
6311
3/4
✓ Branch 0 taken 283 times.
✓ Branch 1 taken 9339 times.
✓ Branch 2 taken 283 times.
✗ Branch 3 not taken.
9622 ret = create ? dd_create_hardcoded(dict_sys_t::s_dict_space_id,
6312 dict_sys_t::s_dd_space_file_name,
6313 dd_space_flags)
6314
1/2
✓ Branch 0 taken 9339 times.
✗ Branch 1 not taken.
9339 : dd_open_hardcoded(dict_sys_t::s_dict_space_id,
6315 dict_sys_t::s_dd_space_file_name,
6316 dd_space_flags);
6317
6318 /* Once hardcoded tablespace mysql is created or opened,
6319 prepare it along with innodb system tablespace for server.
6320 Tell server that these two hardcoded tablespaces exist. */
6321
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 if (!ret) {
6322 9622 const size_t len =
6323 30 + sizeof("id=;flags=;server_version=;space_version=;state=normal");
6324 9622 const char *fmt =
6325 "id=%u;flags=%u;server_version=%u;space_version=%u;state=normal";
6326 static char se_private_data_innodb_system[len];
6327 static char se_private_data_dd[len];
6328 9622 snprintf(se_private_data_innodb_system, len, fmt, TRX_SYS_SPACE,
6329 srv_sys_space.flags(), DD_SPACE_CURRENT_SRV_VERSION,
6330 DD_SPACE_CURRENT_SPACE_VERSION);
6331
6332 9622 snprintf(se_private_data_dd, len, fmt, dict_sys_t::s_dict_space_id,
6333 dd_space_flags, DD_SPACE_CURRENT_SRV_VERSION,
6334 DD_SPACE_CURRENT_SPACE_VERSION);
6335
6336
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 9602 times.
9622 const char *dd_space_options = do_encrypt ? "encryption=y" : "";
6337
6338 static Plugin_tablespace dd_space(dict_sys_t::s_dd_space_name,
6339 dd_space_options, se_private_data_dd, "",
6340
3/8
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
9622 innobase_hton_name);
6341 static Plugin_tablespace::Plugin_tablespace_file dd_file(
6342
2/4
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
9622 dict_sys_t::s_dd_space_file_name, "");
6343
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 dd_space.add_file(&dd_file);
6344
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 tablespaces->push_back(&dd_space);
6345
6346
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 9618 times.
9622 const char *options = srv_sys_space.is_encrypted() ? "encryption=y" : "";
6347
6348 static Plugin_tablespace innodb(dict_sys_t::s_sys_space_name, options,
6349 se_private_data_innodb_system, "",
6350
3/8
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
9622 innobase_hton_name);
6351 9622 Tablespace::files_t::const_iterator end = srv_sys_space.m_files.end();
6352 9622 Tablespace::files_t::const_iterator begin = srv_sys_space.m_files.begin();
6353
2/2
✓ Branch 0 taken 9650 times.
✓ Branch 1 taken 9622 times.
19272 for (Tablespace::files_t::const_iterator it = begin; it != end; ++it) {
6354 9650 innobase_sys_files.push_back(
6355
2/4
✓ Branch 0 taken 9650 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9650 times.
✗ Branch 3 not taken.
9650 ut::new_withkey<Plugin_tablespace::Plugin_tablespace_file>(
6356 9650 UT_NEW_THIS_FILE_PSI_KEY, it->name(), ""));
6357
1/2
✓ Branch 0 taken 9650 times.
✗ Branch 1 not taken.
9650 innodb.add_file(innobase_sys_files.back());
6358 }
6359
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 tablespaces->push_back(&innodb);
6360
6361 } else {
6362 return innodb_init_abort();
6363 }
6364
6365 9622 innobase_old_blocks_pct = static_cast<uint>(
6366
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 buf_LRU_old_ratio_update(innobase_old_blocks_pct, true));
6367
6368
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 ibuf_max_size_update(srv_change_buffer_max_size);
6369
6370
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 innobase_open_tables = ut::new_<hash_table_t>(200);
6371
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 mysql_mutex_init(innobase_share_mutex_key.m_value, &innobase_share_mutex,
6372 MY_MUTEX_INIT_FAST);
6373
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 mysql_mutex_init(commit_cond_mutex_key.m_value, &commit_cond_m,
6374 MY_MUTEX_INIT_FAST);
6375
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 mysql_cond_init(commit_cond_key.m_value, &commit_cond);
6376
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 mysql_mutex_init(resume_encryption_cond_mutex_key.m_value,
6377 &resume_encryption_cond_m, MY_MUTEX_INIT_FAST);
6378
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 mysql_cond_init(resume_encryption_cond_key.m_value, &resume_encryption_cond);
6379 9622 innodb_inited = true;
6380 #ifdef MYSQL_DYNAMIC_PLUGIN
6381 if (innobase_hton != p) {
6382 innobase_hton = reinterpret_cast<handlerton *>(p);
6383 *innobase_hton = *innodb_hton_ptr;
6384 }
6385 #endif /* MYSQL_DYNAMIC_PLUGIN */
6386
6387 /* Do this as late as possible so server is fully starts up,
6388 since we might get some initial stats if user choose to turn
6389 on some counters from start up */
6390
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9620 times.
9622 if (innobase_enable_monitor_counter) {
6391
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 innodb_enable_monitor_at_startup(innobase_enable_monitor_counter);
6392 }
6393
6394 /* Turn on monitor counters that are default on */
6395
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 srv_mon_default_on();
6396
6397 /* Unit Tests */
6398 #ifdef UNIV_ENABLE_UNIT_TEST_GET_PARENT_DIR
6399 unit_test_os_file_get_parent_dir();
6400 #endif /* UNIV_ENABLE_UNIT_TEST_GET_PARENT_DIR */
6401
6402 #ifdef UNIV_ENABLE_UNIT_TEST_MAKE_FILEPATH
6403 test_make_filepath();
6404 #endif /*UNIV_ENABLE_UNIT_TEST_MAKE_FILEPATH */
6405
6406 #ifdef UNIV_ENABLE_DICT_STATS_TEST
6407 test_dict_stats_all();
6408 #endif /*UNIV_ENABLE_DICT_STATS_TEST */
6409
6410 #ifdef UNIV_ENABLE_UNIT_TEST_ROW_RAW_FORMAT_INT
6411 #ifdef HAVE_UT_CHRONO_T
6412 test_row_raw_format_int();
6413 #endif /* HAVE_UT_CHRONO_T */
6414 #endif /* UNIV_ENABLE_UNIT_TEST_ROW_RAW_FORMAT_INT */
6415
6416 9622 return 0;
6417 9706 }
6418
6419 /** Flush InnoDB redo logs to the file system.
6420 @param[in] hton InnoDB handlerton
6421 @param[in] binlog_group_flush true if we got invoked by binlog
6422 group commit during flush stage, false in other cases.
6423 @return false */
6424 2583007 static bool innobase_flush_logs(handlerton *hton, bool binlog_group_flush) {
6425
1/2
✓ Branch 0 taken 2583026 times.
✗ Branch 1 not taken.
2583007 DBUG_TRACE;
6426
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2583026 times.
2583026 assert(hton == innodb_hton_ptr);
6427
6428
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 2582994 times.
2583026 if (srv_read_only_mode) {
6429 32 return false;
6430 }
6431
6432 /* If !binlog_group_flush, we got invoked by FLUSH LOGS or similar.
6433 Else, we got invoked by binlog group commit during flush stage. */
6434
6435
4/4
✓ Branch 0 taken 2497347 times.
✓ Branch 1 taken 85647 times.
✓ Branch 2 taken 33121 times.
✓ Branch 3 taken 2464226 times.
2582994 if (binlog_group_flush && srv_flush_log_at_trx_commit == 0) {
6436 /* innodb_flush_log_at_trx_commit=0
6437 (write and sync once per second).
6438 Do not flush the redo log during binlog group commit. */
6439
6440 /* This could be unsafe if we grouped at least one DDL transaction,
6441 and we removed !trx->ddl_must_flush from condition which is checked
6442 inside trx_commit_complete_for_mysql() when we decide if we could
6443 skip the flush. */
6444 33121 return false;
6445 }
6446
6447 /* Signal and wait for all GTIDs to persist on disk. */
6448
2/2
✓ Branch 0 taken 85650 times.
✓ Branch 1 taken 2464223 times.
2549873 if (!binlog_group_flush) {
6449 85650 auto &gtid_persistor = clone_sys->get_gtid_persistor();
6450
1/2
✓ Branch 0 taken 85650 times.
✗ Branch 1 not taken.
85650 gtid_persistor.wait_flush(true, true, nullptr);
6451 }
6452
6453 /* Flush the redo log buffer to the redo log file.
6454 Sync it to disc if we are in FLUSH LOGS, or if
6455 innodb_flush_log_at_trx_commit=1
6456 (write and sync at each commit). */
6457
3/4
✓ Branch 0 taken 2464226 times.
✓ Branch 1 taken 85647 times.
✓ Branch 2 taken 2549837 times.
✗ Branch 3 not taken.
5014099 log_buffer_flush_to_disk(!binlog_group_flush ||
6458
2/2
✓ Branch 0 taken 2424069 times.
✓ Branch 1 taken 40157 times.
2464226 srv_flush_log_at_trx_commit == 1);
6459
6460 2549837 return false;
6461 2582990 }
6462
6463 /** Commits a transaction in an InnoDB database. */
6464 20743612 void innobase_commit_low(trx_t *trx) /*!< in: transaction handle */
6465 {
6466 #ifdef WITH_WSREP
6467 20743612 THD *thd = (THD *)trx->mysql_thd;
6468
2/2
✓ Branch 0 taken 557638 times.
✓ Branch 1 taken 20186022 times.
20743612 if (wsrep_on(thd)) {
6469 char info[64];
6470 557638 info[sizeof(info) - 1] = '\0';
6471
1/2
✓ Branch 0 taken 557640 times.
✗ Branch 1 not taken.
557638 snprintf(info, sizeof(info) - 1, "innobase_commit_low (%lld)",
6472 (long long)wsrep_thd_trx_seqno(thd));
6473
1/2
✓ Branch 0 taken 557639 times.
✗ Branch 1 not taken.
557640 wsrep_set_thd_proc_info(thd, info);
6474
2/4
✓ Branch 0 taken 557639 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 557640 times.
✗ Branch 3 not taken.
557639 thd_proc_info(thd, wsrep_get_thd_proc_info(thd));
6475 }
6476 #endif /* WITH_WSREP */
6477
6478
2/2
✓ Branch 0 taken 19807382 times.
✓ Branch 1 taken 936280 times.
20743662 DEBUG_SYNC_C("innobase_commit_low_begin");
6479
6480
2/2
✓ Branch 0 taken 16605301 times.
✓ Branch 1 taken 4138384 times.
20743697 if (trx_is_started(trx)) {
6481 16605301 const dberr_t error [[maybe_unused]] = trx_commit_for_mysql(trx);
6482 #ifdef WITH_WSREP
6483 // The original comment is not necessarily true for PXC.
6484 // We removed check for TRX_FORCE_ROLLBACK_DISABLE from 'if' condition in
6485 // lock_make_trx_hit_list(), so now HP transaction can BF other transaction
6486 // even if the flag is set.
6487 // It is OK in general case if local transaction is not empty (so it is
6488 // replicated and certified). If it conflicts with HP transaction it will
6489 // not be certified (so will be discarded), and if it was certified, there
6490 // is no possibility for other transaction to BF it because that other
6491 // transaction should fail certification.
6492 // If local transaction is the empty transaction, it is not replicated
6493 // and certified as it does not generate any writestes. So it follows the
6494 // normal transaction path. But empty transaction can get some locks.
6495 // If at the same time there is replicated transaction attempting to get the
6496 // same locks, it can BF local transaction at any stage, even if local
6497 // transaction is commiting. (note that it can happen only for empty local
6498 // transaction)
6499
5/8
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 16605280 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 16605270 times.
16605281 ut_ad(DB_SUCCESS == error ||
6500 (DB_FORCED_ABORT == error && thd->wsrep_trx().is_empty()));
6501 #else
6502 // This is ut_ad not ut_a, because previously we did not have an assert
6503 // and nobody has noticed for a long time, so probably there is no much
6504 // harm in silencing this error. OTOH we believe it should no longer happen
6505 // after adding `true` as a second argument to TrxInInnoDB constructor call,
6506 // so we'd like to learn if the error can still happen.
6507 ut_ad(DB_SUCCESS == error);
6508 #endif
6509 }
6510 20743654 trx->will_lock = 0;
6511 20743654 }
6512
6513 /** Stores the current binlog coordinates in the trx system header
6514 @param[in] hton InnoDB handlerton
6515 @param[in] thd MySQL thread handle */
6516 249 static int innobase_store_binlog_info(handlerton *hton, THD *thd) noexcept {
6517 249 DBUG_ENTER("innobase_store_binlog_info");
6518
6519 const char *file_name;
6520 unsigned long long pos;
6521 249 thd_binlog_pos(thd, &file_name, &pos);
6522
6523 249 trx_sys_write_binlog_position("", std::numeric_limits<uint64_t>::max(),
6524 file_name, pos);
6525
6526 249 innobase_flush_logs(hton, false);
6527
6528 249 DBUG_RETURN(0);
6529 }
6530
6531 /** Creates an InnoDB transaction struct for the thd if it does not yet have
6532 one. Starts a new InnoDB transaction if a transaction is not yet started. And
6533 assigns a new snapshot for a consistent read if the transaction does not yet
6534 have one.
6535 @return 0 */
6536 64 static int innobase_start_trx_and_assign_read_view(
6537 handlerton *hton, /*!< in: InnoDB handlerton */
6538 THD *thd) /*!< in: MySQL thread handle of the user for
6539 whom the transaction should be committed */
6540 {
6541
1/2
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
64 DBUG_TRACE;
6542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 assert(hton == innodb_hton_ptr);
6543
6544 /* Create a new trx struct for thd, if it does not yet have one */
6545
6546
1/2
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
64 trx_t *trx = check_trx_exists(thd);
6547
6548
1/2
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
64 TrxInInnoDB trx_in_innodb(trx);
6549
6550
1/2
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
64 innobase_srv_conc_force_exit_innodb(trx);
6551
6552 /* The transaction should not be active yet, start it */
6553
2/4
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 64 times.
64 ut_ad(!trx_is_started(trx));
6554
6555
1/2
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
64 trx_start_if_not_started_xa(trx, false, UT_LOCATION_HERE);
6556
6557 /* Assign a read view if the transaction does not have it yet.
6558 Do this only if transaction is using REPEATABLE READ isolation
6559 level. */
6560 64 trx->isolation_level =
6561
2/4
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 64 times.
✗ Branch 3 not taken.
64 innobase_trx_map_isolation_level(thd_get_trx_isolation(thd));
6562
6563
1/2
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
64 if (trx->isolation_level == TRX_ISO_REPEATABLE_READ) {
6564
1/2
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
64 trx_assign_read_view(trx);
6565 } else {
6566 push_warning_printf(thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED,
6567 "InnoDB: WITH CONSISTENT SNAPSHOT"
6568 " was ignored because this phrase"
6569 " can only be used with"
6570 " REPEATABLE READ isolation level.");
6571 }
6572
6573 /* Set the MySQL flag to mark that there is an active transaction */
6574
6575
2/4
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 64 times.
✗ Branch 3 not taken.
64 innobase_register_trx(hton, current_thd, trx);
6576
6577 64 return 0;
6578 64 }
6579
6580 /** Creates an InnoDB transaction struct for the thd if it does not
6581 yet have one. Starts a new InnoDB transaction if a transaction is not
6582 yet started. And clones snapshot for a consistent read from another
6583 session, if it has one.
6584 @param[in] hton InnoDB handlerton
6585 @param[in] thd MySQL thread handle of the user for whom the
6586 transaction should be committed
6587 @param[in] from_thd MySQL thread handle of the user session from
6588 which the consistent read should be cloned
6589 @return 0 */
6590 21 static int innobase_start_trx_and_clone_read_view(handlerton *hton, THD *thd,
6591 THD *from_thd) {
6592
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 DBUG_ENTER("innobase_start_trx_and_clone_read_view");
6593
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 assert(hton == innodb_hton_ptr);
6594
6595 /* Get transaction handle from the donor session */
6596
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 trx_t *const from_trx = thd_to_trx(from_thd);
6597
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (!from_trx) {
6598 push_warning_printf(thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED,
6599 "InnoDB: WITH CONSISTENT SNAPSHOT FROM SESSION was "
6600 "ignored because the specified session does not have "
6601 "an open transaction inside InnoDB.");
6602
6603 DBUG_RETURN(0);
6604 }
6605
6606 /* Create a new trx struct for thd, if it does not yet have one */
6607
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 trx_t *const trx = check_trx_exists(thd);
6608
6609
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 innobase_srv_conc_force_exit_innodb(trx);
6610
6611 /* If the transaction is not started yet, start it */
6612
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 trx_start_if_not_started_xa(trx, false, UT_LOCATION_HERE);
6613
6614 /* Clone the read view from the donor transaction. Do this only if
6615 transaction is using REPEATABLE READ isolation level. */
6616 21 trx->isolation_level =
6617
2/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
21 innobase_trx_map_isolation_level(thd_get_trx_isolation(thd));
6618
6619
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 20 times.
21 if (trx->isolation_level != TRX_ISO_REPEATABLE_READ) {
6620
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 push_warning_printf(thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED,
6621 "InnoDB: WITH CONSISTENT SNAPSHOT was ignored because "
6622 "this phrase can only be used with REPEATABLE READ "
6623 "isolation level.");
6624 } else {
6625
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 locksys::Global_exclusive_latch_guard guard{UT_LOCATION_HERE};
6626
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 trx_sys_mutex_enter();
6627
4/8
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
20 trx_mutex_enter(from_trx);
6628
3/4
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 17 times.
20 if (!trx_clone_read_view(trx, from_trx)) {
6629
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 push_warning_printf(thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED,
6630 "InnoDB: WITH CONSISTENT SNAPSHOT FROM SESSION was "
6631 "ignored because the target transaction has not "
6632 "been assigned a read view.");
6633 }
6634 20 }
6635
6636 /* Set the MySQL flag to mark that there is an active transaction */
6637
2/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
21 innobase_register_trx(hton, current_thd, trx);
6638
6639
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 DBUG_RETURN(0);
6640 }
6641
6642 /** Commits a transaction in an InnoDB database or marks an SQL statement
6643 ended.
6644 @return 0 or deadlock error if the transaction was aborted by another
6645 higher priority transaction. */
6646 28233157 static int innobase_commit(handlerton *hton, /*!< in: InnoDB handlerton */
6647 THD *thd, /*!< in: MySQL thread handle of the
6648 user for whom the transaction should
6649 be committed */
6650 bool commit_trx) /*!< in: true - commit transaction
6651 false - the current SQL statement
6652 ended */
6653 {
6654
1/2
✓ Branch 0 taken 28233295 times.
✗ Branch 1 not taken.
28233157 DBUG_TRACE;
6655
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28233295 times.
28233295 assert(hton == innodb_hton_ptr);
6656
5/8
✓ Branch 0 taken 28233292 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28233289 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1413 times.
✓ Branch 5 taken 28231876 times.
✓ Branch 6 taken 1413 times.
✗ Branch 7 not taken.
28233295 DBUG_PRINT("trans", ("ending transaction"));
6657
3/4
✓ Branch 0 taken 25332987 times.
✓ Branch 1 taken 2900302 times.
✓ Branch 2 taken 25333069 times.
✗ Branch 3 not taken.
28233289 DEBUG_SYNC_C("transaction_commit_start");
6658
6659
1/2
✓ Branch 0 taken 28233299 times.
✗ Branch 1 not taken.
28233371 trx_t *trx = check_trx_exists(thd);
6660
6661 /* We are about to check if the transaction is_aborted, and if it is,
6662 then we want to rollback, and otherwise we want to proceed.
6663 However it might happen that a different transaction, which has high priority
6664 will abort our transaction just after we do the test.
6665 To prevent that, we want to set TRX_FORCE_ROLLBACK_DISABLE flag on our trx,
6666 which is checked in RecLock::make_trx_hit_list and prevents high priority
6667 transaction from killing us.
6668 One way to do that is to call TrxInInnoDB with `true` as second argument.
6669 Note that innobase_commit is called not only on "real" COMMIT, but also
6670 after each statement (with commit_trx=false), so we need some logic to decide
6671 if we really plan to perform commit during this call.
6672 */
6673 bool will_commit =
6674
2/2
✓ Branch 0 taken 26374594 times.
✓ Branch 1 taken 1858705 times.
54607907 commit_trx ||
6675
3/4
✓ Branch 0 taken 26374608 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18874460 times.
✓ Branch 3 taken 7500148 times.
26374594 (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
6676
1/2
✓ Branch 0 taken 28233279 times.
✗ Branch 1 not taken.
28233313 TrxInInnoDB trx_in_innodb(trx, will_commit);
6677
6678
3/4
✓ Branch 0 taken 28233292 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 28233287 times.
28233279 if (trx_in_innodb.is_aborted()) {
6679
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 innobase_rollback(hton, thd, commit_trx);
6680
6681
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, thd);
6682 }
6683
6684
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28233224 times.
28233287 ut_ad(trx->dict_operation_lock_mode == 0);
6685
6686 /* Transaction is deregistered only in a commit or a rollback. If
6687 it is deregistered we know there cannot be resources to be freed
6688 and we could return immediately. For the time being, we play safe
6689 and do the cleanup though there should be nothing to clean up. */
6690
6691
5/8
✓ Branch 0 taken 696219 times.
✓ Branch 1 taken 27536992 times.
✓ Branch 2 taken 696236 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 696236 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 28233228 times.
28233224 if (!trx_is_registered_for_2pc(trx) && trx_is_started(trx)) {
6692 log_errlog(ERROR_LEVEL, ER_INNODB_UNREGISTERED_TRX_ACTIVE);
6693 }
6694
6695
4/4
✓ Branch 0 taken 15674665 times.
✓ Branch 1 taken 12558578 times.
✓ Branch 2 taken 4742936 times.
✓ Branch 3 taken 10931729 times.
28233243 bool read_only = trx->read_only || trx->id == 0;
6696
6697
2/2
✓ Branch 0 taken 20733121 times.
✓ Branch 1 taken 7500122 times.
28233243 if (will_commit) {
6698
4/6
✓ Branch 0 taken 20733127 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 20733124 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
20733121 DBUG_EXECUTE_IF("crash_innodb_before_commit", DBUG_SUICIDE(););
6699 /* We were instructed to commit the whole transaction, or
6700 this is an SQL statement end and autocommit is on */
6701
6702 /* We need current binlog position for mysqlbackup to work. */
6703
6704
2/2
✓ Branch 0 taken 3507807 times.
✓ Branch 1 taken 17225317 times.
20733124 if (!read_only) {
6705
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 3507789 times.
3507807 while (innobase_commit_concurrency > 0) {
6706
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 mysql_mutex_lock(&commit_cond_m);
6707
6708 18 ++commit_threads;
6709
6710
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (commit_threads <= innobase_commit_concurrency) {
6711
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 mysql_mutex_unlock(&commit_cond_m);
6712 18 break;
6713 }
6714
6715 --commit_threads;
6716
6717 mysql_cond_wait(&commit_cond, &commit_cond_m);
6718
6719 mysql_mutex_unlock(&commit_cond_m);
6720 }
6721
6722 /* The following call reads the binary log position of
6723 the transaction being committed.
6724
6725 Binary logging of other engines is not relevant to
6726 InnoDB as all InnoDB requires is that committing
6727 InnoDB transactions appear in the same order in the
6728 MySQL binary log as they appear in InnoDB logs, which
6729 is guaranteed by the server.
6730
6731 If the binary log is not enabled, or the transaction
6732 is not written to the binary log, the file name will
6733 be a NULL pointer. */
6734 ulonglong pos;
6735
6736
1/2
✓ Branch 0 taken 3507811 times.
✗ Branch 1 not taken.
3507807 thd_binlog_pos(thd, &trx->mysql_log_file_name, &pos);
6737
6738 3507811 trx->mysql_log_offset = static_cast<uint64_t>(pos);
6739
6740 /* Don't do write + flush right now. For group commit
6741 to work we want to do the flush later. */
6742 3507811 trx->flush_log_later = true;
6743 }
6744
6745 #ifdef WITH_WSREP
6746 /* If the transaction is not run in 2pc, we must assign wsrep
6747 XID here in order to get it written in rollback segment. */
6748
3/4
✓ Branch 0 taken 20733115 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 557636 times.
✓ Branch 3 taken 20175479 times.
20733128 if (wsrep_on(thd)) {
6749
1/2
✓ Branch 0 taken 557636 times.
✗ Branch 1 not taken.
557636 thd_get_xid(thd, (MYSQL_XID *)trx->xid);
6750 }
6751 #endif /* WITH_WSREP */
6752
6753 /* If SE needs to persist GTID we must have a transaction. */
6754
3/4
✓ Branch 0 taken 20733125 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 218 times.
✓ Branch 3 taken 20732907 times.
20733115 if (thd->se_persists_gtid_explicit()) {
6755
1/2
✓ Branch 0 taken 218 times.
✗ Branch 1 not taken.
218 trx_start_if_not_started(trx, true, UT_LOCATION_HERE);
6756 }
6757
6758
1/2
✓ Branch 0 taken 20733105 times.
✗ Branch 1 not taken.
20733125 innobase_commit_low(trx);
6759
6760
2/2
✓ Branch 0 taken 3507809 times.
✓ Branch 1 taken 17225296 times.
20733105 if (!read_only) {
6761 3507809 trx->flush_log_later = false;
6762
6763
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 3507791 times.
3507809 if (innobase_commit_concurrency > 0) {
6764
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 mysql_mutex_lock(&commit_cond_m);
6765
6766
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 ut_ad(commit_threads > 0);
6767 18 --commit_threads;
6768
6769
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 mysql_cond_signal(&commit_cond);
6770
6771
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 mysql_mutex_unlock(&commit_cond_m);
6772 }
6773 }
6774
6775 20733105 trx_deregister_from_2pc(trx);
6776
6777 /* Now do a write + flush of logs. */
6778
2/2
✓ Branch 0 taken 3507809 times.
✓ Branch 1 taken 17225261 times.
20733070 if (!read_only) {
6779
1/2
✓ Branch 0 taken 3507380 times.
✗ Branch 1 not taken.
3507809 trx_commit_complete_for_mysql(trx);
6780 }
6781
6782 } else {
6783 /* We just mark the SQL statement ended and do not do a
6784 transaction commit */
6785
6786 /* If we had reserved the auto-inc lock for some
6787 table in this SQL statement we release it now */
6788
6789
2/2
✓ Branch 0 taken 7423880 times.
✓ Branch 1 taken 76242 times.
7500122 if (!read_only) {
6790
1/2
✓ Branch 0 taken 7423947 times.
✗ Branch 1 not taken.
7423880 lock_unlock_table_autoinc(trx);
6791 }
6792
6793 /* Store the current undo_no of the transaction so that we
6794 know where to roll back if we have to roll back the next
6795 SQL statement */
6796
6797
1/2
✓ Branch 0 taken 7500144 times.
✗ Branch 1 not taken.
7500189 trx_mark_sql_stat_end(trx);
6798 }
6799
6800 /* Reset the number AUTO-INC rows required */
6801 28232785 trx->n_autoinc_rows = 0;
6802
6803 /* This is a statement level variable. */
6804 28232785 trx->fts_next_doc_id = 0;
6805
6806
1/2
✓ Branch 0 taken 28232828 times.
✗ Branch 1 not taken.
28232785 innobase_srv_conc_force_exit_innodb(trx);
6807
6808 28232828 return 0;
6809 28232833 }
6810
6811 /** Rolls back a transaction or the latest SQL statement.
6812 @return 0 or error number */
6813 646949 static int innobase_rollback(handlerton *hton, /*!< in: InnoDB handlerton */
6814 THD *thd, /*!< in: handle to the MySQL thread
6815 of the user whose transaction should
6816 be rolled back */
6817 bool rollback_trx) /*!< in: true - rollback entire
6818 transaction false - rollback the
6819 current statement only */
6820 {
6821
1/2
✓ Branch 0 taken 646953 times.
✗ Branch 1 not taken.
646949 DBUG_TRACE;
6822
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 646953 times.
646953 assert(hton == innodb_hton_ptr);
6823
3/8
✓ Branch 0 taken 646953 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 646954 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 646954 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
646953 DBUG_PRINT("trans", ("aborting transaction"));
6824
6825
1/2
✓ Branch 0 taken 646953 times.
✗ Branch 1 not taken.
646954 trx_t *trx = check_trx_exists(thd);
6826
6827
1/2
✓ Branch 0 taken 646952 times.
✗ Branch 1 not taken.
646953 TrxInInnoDB trx_in_innodb(trx);
6828
6829
6/10
✓ Branch 0 taken 646950 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 646490 times.
✓ Branch 3 taken 460 times.
✓ Branch 4 taken 646491 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 646492 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 646951 times.
646952 ut_ad(trx_in_innodb.is_aborted() ||
6830 (trx->dict_operation_lock_mode == 0 &&
6831 trx->dict_operation == TRX_DICT_OP_NONE));
6832
6833
1/2
✓ Branch 0 taken 646953 times.
✗ Branch 1 not taken.
646951 innobase_srv_conc_force_exit_innodb(trx);
6834
6835 /* Reset the number AUTO-INC rows required */
6836
6837 646953 trx->n_autoinc_rows = 0;
6838
6839 /* If we had reserved the auto-inc lock for some table (if
6840 we come here to roll back the latest SQL statement) we
6841 release it now before a possibly lengthy rollback */
6842
6843
3/4
✓ Branch 0 taken 646954 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 646494 times.
✓ Branch 3 taken 460 times.
646953 if (!trx_in_innodb.is_aborted()) {
6844
1/2
✓ Branch 0 taken 646493 times.
✗ Branch 1 not taken.
646494 lock_unlock_table_autoinc(trx);
6845 }
6846
6847 /* This is a statement level variable. */
6848
6849 646953 trx->fts_next_doc_id = 0;
6850
6851 dberr_t error;
6852
6853 #ifdef WITH_WSREP
6854 /* If trx was assigned wsrep XID in prepare phase and the
6855 trx is being rolled back due to BF abort, clear XID in order
6856 to avoid writing it to rollback segment out of order. The XID
6857 will be reassigned when the transaction is replayed. */
6858
7/8
✓ Branch 0 taken 630110 times.
✓ Branch 1 taken 16844 times.
✓ Branch 2 taken 630111 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 71 times.
✓ Branch 5 taken 630040 times.
✓ Branch 6 taken 71 times.
✓ Branch 7 taken 646884 times.
646953 if (trx->state != TRX_STATE_NOT_STARTED && wsrep_is_wsrep_xid(trx->xid)) {
6859 71 trx->xid->reset();
6860 }
6861 #endif /* WITH_WSREP */
6862
6863
4/4
✓ Branch 0 taken 636797 times.
✓ Branch 1 taken 10158 times.
✓ Branch 2 taken 639728 times.
✓ Branch 3 taken 7227 times.
1283752 if (rollback_trx ||
6864
3/4
✓ Branch 0 taken 636797 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 629570 times.
✓ Branch 3 taken 7227 times.
636797 !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
6865
1/2
✓ Branch 0 taken 639715 times.
✗ Branch 1 not taken.
639728 error = trx_rollback_for_mysql(trx);
6866
6867
2/4
✓ Branch 0 taken 639716 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 639716 times.
639715 ut_ad(trx_can_be_handled_by_current_thread_or_is_hp_victim(trx));
6868
2/2
✓ Branch 0 taken 461 times.
✓ Branch 1 taken 639255 times.
639716 if (trx->state.load(std::memory_order_relaxed) ==
6869 TRX_STATE_FORCED_ROLLBACK) {
6870 #ifdef UNIV_DEBUG
6871 char buffer[1024];
6872
6873
1/2
✓ Branch 0 taken 461 times.
✗ Branch 1 not taken.
461 ib::info(ER_IB_MSG_548)
6874
1/2
✓ Branch 0 taken 461 times.
✗ Branch 1 not taken.
461 << "Forced rollback : "
6875
2/4
✓ Branch 0 taken 461 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 461 times.
✗ Branch 3 not taken.
461 << thd_security_context(thd, buffer, sizeof(buffer), 512);
6876 #endif /* UNIV_DEBUG */
6877 461 trx->state.store(TRX_STATE_NOT_STARTED, std::memory_order_relaxed);
6878 }
6879
6880 639716 trx_deregister_from_2pc(trx);
6881
6882 } else {
6883
1/2
✓ Branch 0 taken 7226 times.
✗ Branch 1 not taken.
7227 error = trx_rollback_last_sql_stat_for_mysql(trx);
6884 }
6885
6886
1/2
✓ Branch 0 taken 646941 times.
✗ Branch 1 not taken.
1293883 return convert_error_code_to_mysql(error, 0, trx->mysql_thd);
6887 646941 }
6888
6889 /** Rolls back a transaction
6890 @return 0 or error number */
6891 15660341 static int innobase_rollback_trx(trx_t *trx) /*!< in: transaction */
6892 {
6893 15660341 dberr_t error = DB_SUCCESS;
6894
6895
1/2
✓ Branch 0 taken 15660814 times.
✗ Branch 1 not taken.
15660341 DBUG_TRACE;
6896
5/8
✓ Branch 0 taken 15660602 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15660769 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1171 times.
✓ Branch 5 taken 15659598 times.
✓ Branch 6 taken 1171 times.
✗ Branch 7 not taken.
15660814 DBUG_PRINT("trans", ("aborting transaction"));
6897
6898
1/2
✓ Branch 0 taken 15660610 times.
✗ Branch 1 not taken.
15660769 innobase_srv_conc_force_exit_innodb(trx);
6899
6900 /* If we had reserved the auto-inc lock for some table (if
6901 we come here to roll back the latest SQL statement) we
6902 release it now before a possibly lengthy rollback */
6903
3/4
✓ Branch 0 taken 15660715 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15660705 times.
✓ Branch 3 taken 10 times.
15660610 if (!TrxInInnoDB::is_aborted(trx)) {
6904
1/2
✓ Branch 0 taken 15660835 times.
✗ Branch 1 not taken.
15660705 lock_unlock_table_autoinc(trx);
6905 }
6906
6907
2/2
✓ Branch 0 taken 408 times.
✓ Branch 1 taken 15660482 times.
15660845 if (trx_is_rseg_updated(trx)) {
6908
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
408 error = trx_rollback_for_mysql(trx);
6909 } else {
6910 15660482 trx->will_lock = 0;
6911 }
6912
6913
1/2
✓ Branch 0 taken 15660766 times.
✗ Branch 1 not taken.
31321685 return convert_error_code_to_mysql(error, 0, trx->mysql_thd);
6914 15660766 }
6915
6916 /** Rolls back a transaction to a savepoint.
6917 @return 0 if success, HA_ERR_NO_SAVEPOINT if no savepoint with the
6918 given name */
6919 4219 static int innobase_rollback_to_savepoint(
6920 handlerton *hton, /*!< in: InnoDB handlerton */
6921 THD *thd, /*!< in: handle to the MySQL thread
6922 of the user whose transaction should
6923 be rolled back to savepoint */
6924 void *savepoint) /*!< in: savepoint data */
6925 {
6926
1/2
✓ Branch 0 taken 4219 times.
✗ Branch 1 not taken.
4219 DBUG_TRACE;
6927
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4219 times.
4219 assert(hton == innodb_hton_ptr);
6928
6929
1/2
✓ Branch 0 taken 4219 times.
✗ Branch 1 not taken.
4219 trx_t *trx = check_trx_exists(thd);
6930
6931
1/2
✓ Branch 0 taken 4219 times.
✗ Branch 1 not taken.
4219 TrxInInnoDB trx_in_innodb(trx);
6932
6933
1/2
✓ Branch 0 taken 4219 times.
✗ Branch 1 not taken.
4219 innobase_srv_conc_force_exit_innodb(trx);
6934
6935 /* TODO: use provided savepoint data area to store savepoint data */
6936
6937 char name[64];
6938
6939
1/2
✓ Branch 0 taken 4219 times.
✗ Branch 1 not taken.
4219 longlong2str((ulint)savepoint, name, 36);
6940
6941 int64_t mysql_binlog_cache_pos;
6942
6943 dberr_t error =
6944
1/2
✓ Branch 0 taken 4219 times.
✗ Branch 1 not taken.
4219 trx_rollback_to_savepoint_for_mysql(trx, name, &mysql_binlog_cache_pos);
6945
6946
3/4
✓ Branch 0 taken 4219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 4202 times.
4219 if (error == DB_SUCCESS && trx->fts_trx != nullptr) {
6947
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 fts_savepoint_rollback(trx, name);
6948 }
6949
6950
1/2
✓ Branch 0 taken 4219 times.
✗ Branch 1 not taken.
8438 return convert_error_code_to_mysql(error, 0, nullptr);
6951 4219 }
6952
6953 /** Check whether innodb state allows to safely release MDL locks after
6954 rollback to savepoint.
6955 When binlog is on, MDL locks acquired after savepoint unit are not
6956 released if there are any locks held in InnoDB.
6957 @return true if it is safe, false if its not safe. */
6958 4204 static bool innobase_rollback_to_savepoint_can_release_mdl(
6959 handlerton *hton, /*!< in: InnoDB handlerton */
6960 THD *thd) /*!< in: handle to the MySQL thread
6961 of the user whose transaction should
6962 be rolled back to savepoint */
6963 {
6964
1/2
✓ Branch 0 taken 4204 times.
✗ Branch 1 not taken.
4204 DBUG_TRACE;
6965
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4204 times.
4204 assert(hton == innodb_hton_ptr);
6966
6967
1/2
✓ Branch 0 taken 4204 times.
✗ Branch 1 not taken.
4204 trx_t *trx = check_trx_exists(thd);
6968
6969
1/2
✓ Branch 0 taken 4204 times.
✗ Branch 1 not taken.
4204 TrxInInnoDB trx_in_innodb(trx);
6970
6971
2/4
✓ Branch 0 taken 4204 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4204 times.
4204 ut_ad(thd == current_thd);
6972
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4204 times.
4204 ut_ad(trx->lock.wait_lock == nullptr);
6973
1/2
✓ Branch 0 taken 4204 times.
✗ Branch 1 not taken.
8408 return UT_LIST_GET_LEN(trx->lock.trx_locks) == 0;
6974 4204 }
6975
6976 /** Release transaction savepoint name.
6977 @return 0 if success, HA_ERR_NO_SAVEPOINT if no savepoint with the
6978 given name */
6979 126 static int innobase_release_savepoint(
6980 handlerton *hton, /*!< in: handlerton for InnoDB */
6981 THD *thd, /*!< in: handle to the MySQL thread
6982 of the user whose transaction's
6983 savepoint should be released */
6984 void *savepoint) /*!< in: savepoint data */
6985 {
6986 dberr_t error;
6987 trx_t *trx;
6988 char name[64];
6989
6990
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
126 DBUG_TRACE;
6991
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
126 assert(hton == innodb_hton_ptr);
6992
6993
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
126 trx = check_trx_exists(thd);
6994
6995
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
126 TrxInInnoDB trx_in_innodb(trx);
6996
6997 /* TODO: use provided savepoint data area to store savepoint data */
6998
6999
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
126 longlong2str((ulint)savepoint, name, 36);
7000
7001
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
126 error = trx_release_savepoint_for_mysql(trx, name);
7002
7003
3/4
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 114 times.
126 if (error == DB_SUCCESS && trx->fts_trx != nullptr) {
7004
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 fts_savepoint_release(trx, name);
7005 }
7006
7007
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
252 return convert_error_code_to_mysql(error, 0, nullptr);
7008 126 }
7009
7010 /** Sets a transaction savepoint.
7011 @return always 0, that is, always succeeds */
7012 8201 static int innobase_savepoint(
7013 handlerton *hton, /*!< in: handle to the InnoDB handlerton */
7014 THD *thd, /*!< in: handle to the MySQL thread */
7015 void *savepoint) /*!< in: savepoint data */
7016 {
7017
1/2
✓ Branch 0 taken 8202 times.
✗ Branch 1 not taken.
8201 DBUG_TRACE;
7018
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8202 times.
8202 assert(hton == innodb_hton_ptr);
7019
7020 /* In the autocommit mode there is no sense to set a savepoint
7021 (unless we are in sub-statement), so SQL layer ensures that
7022 this method is never called in such situation. */
7023
7024
1/2
✓ Branch 0 taken 8203 times.
✗ Branch 1 not taken.
8202 trx_t *trx = check_trx_exists(thd);
7025
7026
1/2
✓ Branch 0 taken 8203 times.
✗ Branch 1 not taken.
8203 TrxInInnoDB trx_in_innodb(trx);
7027
7028
1/2
✓ Branch 0 taken 8201 times.
✗ Branch 1 not taken.
8203 innobase_srv_conc_force_exit_innodb(trx);
7029
7030 /* Cannot happen outside of transaction */
7031
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8203 times.
8201 assert(trx_is_registered_for_2pc(trx));
7032
7033 /* TODO: use provided savepoint data area to store savepoint data */
7034 char name[64];
7035
7036
1/2
✓ Branch 0 taken 8203 times.
✗ Branch 1 not taken.
8203 longlong2str((ulint)savepoint, name, 36);
7037
7038
1/2
✓ Branch 0 taken 8203 times.
✗ Branch 1 not taken.
8203 dberr_t error = trx_savepoint_for_mysql(trx, name, 0);
7039
7040
3/4
✓ Branch 0 taken 8203 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 8151 times.
8203 if (error == DB_SUCCESS && trx->fts_trx != nullptr) {
7041
1/2
✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
52 fts_savepoint_take(trx->fts_trx, name);
7042 }
7043
7044
1/2
✓ Branch 0 taken 8202 times.
✗ Branch 1 not taken.
16406 return convert_error_code_to_mysql(error, 0, nullptr);
7045 8202 }
7046
7047 /** Frees a possible InnoDB trx object associated with the current THD.
7048 @return 0 or error number */
7049 15660708 static int innobase_close_connection(
7050 handlerton *hton, /*!< in: innobase handlerton */
7051 THD *thd) /*!< in: handle to the MySQL thread of the user
7052 whose resources should be free'd */
7053 {
7054
1/2
✓ Branch 0 taken 15660801 times.
✗ Branch 1 not taken.
15660708 DBUG_TRACE;
7055
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15660801 times.
15660801 assert(hton == innodb_hton_ptr);
7056
7057
1/2
✓ Branch 0 taken 15660775 times.
✗ Branch 1 not taken.
15660801 trx_t *trx = thd_to_trx(thd);
7058 15660775 bool free_trx = false;
7059
7060 /* During server initialization MySQL layer will try to open
7061 some of the master-slave tables those residing in InnoDB.
7062 After MySQL layer is done with needed checks these tables
7063 are closed followed by invocation of close_connection on the
7064 associated thd.
7065
7066 close_connection rolls back the trx and then frees it.
7067 Once trx is freed thd should avoid maintaining reference to
7068 it else it can be classified as stale reference.
7069
7070 Re-invocation of innodb_close_connection on same thd should
7071 get trx as NULL. */
7072
7073
2/2
✓ Branch 0 taken 15660588 times.
✓ Branch 1 taken 187 times.
15660775 if (trx != nullptr) {
7074
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15660567 times.
15660588 ut_ad(trx->mysql_thd == thd);
7075
1/2
✓ Branch 0 taken 15660360 times.
✗ Branch 1 not taken.
15660567 TrxInInnoDB trx_in_innodb(trx);
7076
7077
2/4
✓ Branch 0 taken 15660329 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15660329 times.
15660360 if (trx_in_innodb.is_aborted()) {
7078 while (trx_is_started(trx)) {
7079 std::this_thread::sleep_for(std::chrono::microseconds(20));
7080 }
7081 }
7082
7083
5/8
✓ Branch 0 taken 15660111 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 15660415 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 15660415 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 15660438 times.
15660329 if (!trx_is_registered_for_2pc(trx) && trx_is_started(trx)) {
7084 log_errlog(ERROR_LEVEL, ER_INNODB_UNREGISTERED_TRX_ACTIVE);
7085 }
7086
7087 /* Disconnect causes rollback in the following cases:
7088 - trx is not started, or
7089 - trx is in *not* in PREPARED state, or
7090 - trx has not updated any persistent data.
7091 TODO/FIXME: it does not make sense to initiate rollback
7092 in the 1st and 3rd case. */
7093
3/4
✓ Branch 0 taken 15660407 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 15660405 times.
15660438 if (trx_is_started(trx)) {
7094
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 if (trx_state_eq(trx, TRX_STATE_PREPARED)) {
7095
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (trx_is_redo_rseg_updated(trx)) {
7096
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 trx_disconnect_prepared(trx);
7097 } else {
7098 trx_rollback_for_mysql(trx);
7099 trx_deregister_from_2pc(trx);
7100 free_trx = true;
7101 }
7102 } else {
7103 log_errlog(WARNING_LEVEL, ER_INNODB_CLOSING_CONNECTION_ROLLS_BACK,
7104 trx->undo_no);
7105 ut_d(ib::warn(ER_IB_MSG_549)
7106 << "trx: " << trx << " started on: "
7107 << innobase_basename(trx->start_file) << ":" << trx->start_line);
7108 innobase_rollback_trx(trx);
7109 free_trx = true;
7110 }
7111 } else {
7112
1/2
✓ Branch 0 taken 15660455 times.
✗ Branch 1 not taken.
15660405 innobase_rollback_trx(trx);
7113 15660455 free_trx = true;
7114 }
7115 15660457 }
7116
7117 /* Free trx only after TrxInInnoDB is deleted. */
7118
2/2
✓ Branch 0 taken 15660532 times.
✓ Branch 1 taken 188 times.
15660720 if (free_trx) {
7119
1/2
✓ Branch 0 taken 15660620 times.
✗ Branch 1 not taken.
15660532 trx_free_for_mysql(trx);
7120 }
7121
7122
1/2
✓ Branch 0 taken 15660829 times.
✗ Branch 1 not taken.
15660808 ut::delete_(thd_to_innodb_session(thd));
7123
7124
1/2
✓ Branch 0 taken 15660828 times.
✗ Branch 1 not taken.
15660828 thd_to_innodb_session(thd) = nullptr;
7125
7126 15660828 return 0;
7127 15660828 }
7128
7129 /** Cancel any pending lock request associated with the current THD. */
7130 1431 static void innobase_kill_connection(
7131 handlerton *hton, /*!< in: innobase handlerton */
7132 THD *thd) /*!< in: handle to the MySQL thread being
7133 killed */
7134 {
7135
1/2
✓ Branch 0 taken 1431 times.
✗ Branch 1 not taken.
1431 DBUG_TRACE;
7136
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1431 times.
1431 assert(hton == innodb_hton_ptr);
7137
7138
1/2
✓ Branch 0 taken 1431 times.
✗ Branch 1 not taken.
1431 trx_t *trx = thd_to_trx(thd);
7139
7140
1/2
✓ Branch 0 taken 1431 times.
✗ Branch 1 not taken.
1431 if (trx != nullptr) {
7141 /* Cancel a pending lock request if there are any */
7142
2/4
✓ Branch 0 taken 1431 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1431 times.
✗ Branch 3 not taken.
1431 lock_cancel_if_waiting_and_release({trx});
7143 }
7144 1431 }
7145
7146 /** ** InnoDB database tables
7147 *****************************************************************************/
7148
7149 /** The requested compressed page size (key_block_size)
7150 is given in kilobytes. If it is a valid number, store
7151 that value as the number of log2 shifts from 512 in
7152 zip_ssize. Zero means it is not compressed. */
7153 572 static uint32_t get_zip_shift_size(ulint key_block_size) {
7154 uint32_t zssize; /* Zip Shift Size */
7155 uint32_t kbsize; /* Key Block Size */
7156 const uint32_t zip_ssize_max =
7157 1144 std::min(static_cast<uint32_t>(UNIV_PAGE_SSIZE_MAX),
7158 572 static_cast<uint32_t>(PAGE_ZIP_SSIZE_MAX));
7159
2/2
✓ Branch 0 taken 1548 times.
✓ Branch 1 taken 10 times.
1558 for (zssize = kbsize = 1; zssize <= zip_ssize_max; zssize++, kbsize <<= 1) {
7160
2/2
✓ Branch 0 taken 562 times.
✓ Branch 1 taken 986 times.
1548 if (kbsize == key_block_size) {
7161 562 return (zssize);
7162 }
7163 }
7164 10 return (0);
7165 }
7166
7167 /** Get real row type for the table created based on one specified by user,
7168 CREATE TABLE options and SE capabilities.
7169
7170 @note The current code in this method is redundant with/copy of code from
7171 create_table_info_t::innobase_table_flags(). This is temporary workaround.
7172 In future this method will always return ROW_TYPE_DYNAMIC
7173 (which is suitable for intrisinc temporary tables)
7174 and rely on adjusting row format in table definition at ha_innobase::create()
7175 or ha_innobase::prepare_inplace_alter_table() time.
7176 */
7177 731284 enum row_type ha_innobase::get_real_row_type(
7178 const HA_CREATE_INFO *create_info) const {
7179 731284 const bool is_temp = create_info->options & HA_LEX_CREATE_TMP_TABLE;
7180 731284 row_type rt = create_info->row_type;
7181
7182
4/4
✓ Branch 0 taken 188490 times.
✓ Branch 1 taken 542794 times.
✓ Branch 2 taken 145947 times.
✓ Branch 3 taken 42543 times.
731284 if (is_temp && (create_info->options & HA_LEX_CREATE_INTERNAL_TMP_TABLE)) {
7183 145947 return (ROW_TYPE_DYNAMIC);
7184 }
7185
7186
2/2
✓ Branch 0 taken 163 times.
✓ Branch 1 taken 219045 times.
219208 if (rt == ROW_TYPE_DEFAULT && create_info->key_block_size &&
7187
10/10
✓ Branch 0 taken 219208 times.
✓ Branch 1 taken 366129 times.
✓ Branch 2 taken 156 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 149 times.
✓ Branch 5 taken 7 times.
✓ Branch 6 taken 10 times.
✓ Branch 7 taken 139 times.
✓ Branch 8 taken 140 times.
✓ Branch 9 taken 585197 times.
804555 get_zip_shift_size(create_info->key_block_size) && !is_temp &&
7188
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9 times.
10 (srv_file_per_table || tablespace_is_shared_space(create_info))) {
7189 140 rt = ROW_TYPE_COMPRESSED;
7190 }
7191
7192
4/4
✓ Branch 0 taken 365103 times.
✓ Branch 1 taken 1154 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 219069 times.
585337 switch (rt) {
7193 365103 case ROW_TYPE_REDUNDANT:
7194 case ROW_TYPE_DYNAMIC:
7195 case ROW_TYPE_COMPACT:
7196 365103 return (rt);
7197 1154 case ROW_TYPE_COMPRESSED:
7198
6/6
✓ Branch 0 taken 1128 times.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 1115 times.
✓ Branch 4 taken 1118 times.
✓ Branch 5 taken 36 times.
1167 if (!is_temp &&
7199
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 10 times.
13 (srv_file_per_table || tablespace_is_shared_space(create_info))) {
7200 1118 return (rt);
7201 } else {
7202 36 return (ROW_TYPE_DYNAMIC);
7203 }
7204 11 case ROW_TYPE_NOT_USED:
7205 case ROW_TYPE_FIXED:
7206 case ROW_TYPE_PAGED:
7207 11 return (ROW_TYPE_DYNAMIC);
7208 219069 case ROW_TYPE_DEFAULT:
7209 default:
7210
4/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 93 times.
✓ Branch 2 taken 218961 times.
✓ Branch 3 taken 2 times.
219069 switch (innodb_default_row_format) {
7211 13 case DEFAULT_ROW_FORMAT_REDUNDANT:
7212 13 return (ROW_TYPE_REDUNDANT);
7213 93 case DEFAULT_ROW_FORMAT_COMPACT:
7214 93 return (ROW_TYPE_COMPACT);
7215 218961 case DEFAULT_ROW_FORMAT_DYNAMIC:
7216 218961 return (ROW_TYPE_DYNAMIC);
7217 2 default:
7218 2 ut_d(ut_error);
7219 ut_o(return (ROW_TYPE_DYNAMIC));
7220 }
7221 }
7222 }
7223
7224 /** Get the table flags to use for the statement.
7225 @return table flags */
7226
7227 250393175 handler::Table_flags ha_innobase::table_flags() const {
7228 250393175 THD *thd = ha_thd();
7229 250395531 handler::Table_flags flags = m_int_table_flags;
7230
7231 /* If querying the table flags when no table_share is given,
7232 then we must check if the table to be created/checked is partitioned.
7233 */
7234
6/6
✓ Branch 0 taken 2828662 times.
✓ Branch 1 taken 247566869 times.
✓ Branch 2 taken 25881 times.
✓ Branch 3 taken 2802899 times.
✓ Branch 4 taken 25881 times.
✓ Branch 5 taken 250369768 times.
250395531 if (table_share == nullptr && thd_get_work_part_info(thd) != nullptr) {
7235 /* Currently ha_innopart does not support
7236 all InnoDB features such as GEOMETRY, FULLTEXT etc. */
7237 25881 flags &= ~(HA_INNOPART_DISABLED_TABLE_FLAGS);
7238 }
7239
7240 /* Temporary table provides accurate record count */
7241
2/2
✓ Branch 0 taken 247566888 times.
✓ Branch 1 taken 2828761 times.
250395649 if (table_share != nullptr &&
7242
2/2
✓ Branch 0 taken 677044 times.
✓ Branch 1 taken 246889844 times.
247566888 table_share->table_category == TABLE_CATEGORY_TEMPORARY) {
7243 677044 flags |= HA_STATS_RECORDS_IS_EXACT;
7244 }
7245
7246 /* Need to use tx_isolation here since table flags is (also)
7247 called before prebuilt is inited. */
7248
7249 250395649 ulong const tx_isolation = thd_tx_isolation(thd);
7250
7251
2/2
✓ Branch 0 taken 156370828 times.
✓ Branch 1 taken 94024502 times.
250395330 if (tx_isolation <= ISO_READ_COMMITTED) {
7252 156370828 return (flags);
7253 }
7254
7255 94024502 return (flags | HA_BINLOG_STMT_CAPABLE);
7256 }
7257
7258 /** Returns the table type (storage engine name).
7259 @return table type */
7260
7261 148055 const char *ha_innobase::table_type() const { return (innobase_hton_name); }
7262
7263 /** Returns the operations supported for indexes.
7264 @return flags of supported operations */
7265
7266 43268747 ulong ha_innobase::index_flags(uint key, uint, bool) const {
7267
2/2
✓ Branch 0 taken 16802 times.
✓ Branch 1 taken 43251945 times.
43268747 if (table_share->key_info[key].algorithm == HA_KEY_ALG_FULLTEXT) {
7268 16802 return (0);
7269 }
7270
7271 43251945 ulong flags = HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER | HA_READ_RANGE |
7272 HA_KEYREAD_ONLY | HA_DO_INDEX_COND_PUSHDOWN;
7273
7274 /* For spatial index, we don't support descending scan
7275 and ICP so far. */
7276
2/2
✓ Branch 0 taken 9263 times.
✓ Branch 1 taken 43242682 times.
43251945 if (table_share->key_info[key].flags & HA_SPATIAL) {
7277 9263 flags = HA_READ_NEXT | HA_READ_ORDER | HA_READ_RANGE | HA_KEYREAD_ONLY |
7278 HA_KEY_SCAN_NOT_ROR;
7279 9263 return (flags);
7280 }
7281
7282 /* For dd tables mysql.*, we disable ICP for them,
7283 it's for avoiding recusively access same page. */
7284 /* TODO: Remove these code once the recursiveely access issue which
7285 caused by ICP fixed. */
7286 43242682 const char *dbname = table_share->db.str;
7287
4/4
✓ Branch 0 taken 41405159 times.
✓ Branch 1 taken 1837523 times.
✓ Branch 2 taken 28539052 times.
✓ Branch 3 taken 12866107 times.
43242682 if (dbname && strstr(dbname, dict_sys_t::s_dd_space_name) != nullptr &&
7288
2/2
✓ Branch 0 taken 28354042 times.
✓ Branch 1 taken 185010 times.
28539052 strlen(dbname) == 5) {
7289 28354042 flags = HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER | HA_READ_RANGE |
7290 HA_KEYREAD_ONLY;
7291 }
7292
7293 /* Multi-valued keys don't support ordered retrieval, neither they're
7294 suitable for keyread only retrieval. */
7295
2/2
✓ Branch 0 taken 6358 times.
✓ Branch 1 taken 43236324 times.
43242682 if (table_share->key_info[key].flags & HA_MULTI_VALUED_KEY) {
7296 6358 flags &= ~(HA_READ_ORDER | HA_KEYREAD_ONLY);
7297 }
7298
7299 43242682 return (flags);
7300 }
7301
7302 /** Returns the maximum number of keys.
7303 @return MAX_KEY */
7304
7305 586811 uint ha_innobase::max_supported_keys() const { return (MAX_KEY); }
7306
7307 /** Returns the maximum key length.
7308 @return maximum supported key length, in bytes */
7309
7310 1221866 uint ha_innobase::max_supported_key_length() const {
7311 /* An InnoDB page must store >= 2 keys; a secondary key record
7312 must also contain the primary key value. Therefore, if both
7313 the primary key and the secondary key are at this maximum length,
7314 it must be less than 1/4th of the free space on a page including
7315 record overhead.
7316
7317 MySQL imposes its own limit to this number; MAX_KEY_LENGTH = 3072.
7318
7319 For page sizes = 16k, InnoDB historically reported 3500 bytes here,
7320 But the MySQL limit of 3072 was always used through the handler
7321 interface. */
7322
7323
1/3
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 1221866 times.
1221866 switch (UNIV_PAGE_SIZE) {
7324 case 4096:
7325 return (768);
7326 case 8192:
7327 return (1536);
7328 1221866 default:
7329 1221866 return (3500);
7330 }
7331 }
7332
7333 /** Determines if the primary key is clustered index.
7334 @return true */
7335
7336 12037882 bool ha_innobase::primary_key_is_clustered() const { return (true); }
7337
7338 5969570 bool create_table_info_t::normalize_table_name(char *norm_name,
7339 const char *name) {
7340 const char *name_ptr;
7341 ulint name_len;
7342 const char *db_ptr;
7343 ulint db_len;
7344 const char *ptr;
7345 ulint norm_len;
7346
7347 /* Scan name from the end */
7348
7349 5969570 ptr = strend(name) - 1;
7350
7351 /* seek to the last path separator */
7352
6/6
✓ Branch 0 taken 79373321 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 79373299 times.
✓ Branch 3 taken 22 times.
✓ Branch 4 taken 73403734 times.
✓ Branch 5 taken 5969565 times.
79373323 while (ptr >= name && *ptr != '\\' && *ptr != '/') {
7353 73403734 ptr--;
7354 }
7355
7356 5969589 name_ptr = ptr + 1;
7357 5969589 name_len = strlen(name_ptr);
7358
7359 /* skip any number of path separators */
7360
5/6
✓ Branch 0 taken 11939179 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11939183 times.
✓ Branch 4 taken 5969597 times.
✓ Branch 5 taken 5969586 times.
11939182 while (ptr >= name && (*ptr == '\\' || *ptr == '/')) {
7361 5969593 ptr--;
7362 }
7363
7364
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5969589 times.
5969589 assert(ptr >= name);
7365
7366 /* seek to the last but one path separator or one char before
7367 the beginning of name */
7368 5969589 db_len = 0;
7369
6/6
✓ Branch 0 taken 37083009 times.
✓ Branch 1 taken 114630 times.
✓ Branch 2 taken 37082998 times.
✓ Branch 3 taken 11 times.
✓ Branch 4 taken 31228050 times.
✓ Branch 5 taken 5854948 times.
37197639 while (ptr >= name && *ptr != '\\' && *ptr != '/') {
7370 31228050 ptr--;
7371 31228050 db_len++;
7372 }
7373
7374 5969589 db_ptr = ptr + 1;
7375
7376 5969589 norm_len = db_len + name_len + sizeof "/";
7377
7378
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5969589 times.
5969589 if (norm_len >= FN_REFLEN - 1) {
7379 /* purecov: begin assert */
7380 ut_d(ut_error);
7381 ut_o(return (false));
7382 /* purecov: end */
7383 }
7384
7385 5969589 memcpy(norm_name, db_ptr, db_len);
7386
7387 5969589 norm_name[db_len] = '/';
7388
7389 /* Copy the name and null-byte. */
7390 5969589 memcpy(norm_name + db_len + 1, name_ptr, name_len + 1);
7391
7392
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5969589 times.
5969589 if (lower_case_file_system) {
7393 ut_ad(lower_case_table_names != 0);
7394 innobase_casedn_str(norm_name);
7395 }
7396 5969577 return (true);
7397 }
7398
7399 #ifdef UNIV_DEBUG
7400 /*********************************************************************
7401 Test normalize_table_name(). */
7402 static void test_normalize_table_name() {
7403 char norm_name[FN_REFLEN];
7404 const char *test_data[][2] = {
7405 /* input, expected result */
7406 {"./mysqltest/t1", "mysqltest/t1"},
7407 {"./test/#sql-842b_2", "test/#sql-842b_2"},
7408 {"./test/#sql-85a3_10", "test/#sql-85a3_10"},
7409 {"./test/#sql2-842b-2", "test/#sql2-842b-2"},
7410 {"./test/bug29807", "test/bug29807"},
7411 {"./test/foo", "test/foo"},
7412 {"./test/innodb_bug52663", "test/innodb_bug52663"},
7413 {"./test/t", "test/t"},
7414 {"./test/t1", "test/t1"},
7415 {"./test/t10", "test/t10"},
7416 {"/a/b/db/table", "db/table"},
7417 {"/a/b/db///////table", "db/table"},
7418 {"/a/b////db///////table", "db/table"},
7419 {"/var/tmp/mysqld.1/#sql842b_2_10", "mysqld.1/#sql842b_2_10"},
7420 {"db/table", "db/table"},
7421 {"ddd/t", "ddd/t"},
7422 {"d/ttt", "d/ttt"},
7423 {"d/t", "d/t"},
7424 {".\\mysqltest\\t1", "mysqltest/t1"},
7425 {".\\test\\#sql-842b_2", "test/#sql-842b_2"},
7426 {".\\test\\#sql-85a3_10", "test/#sql-85a3_10"},
7427 {".\\test\\#sql2-842b-2", "test/#sql2-842b-2"},
7428 {".\\test\\bug29807", "test/bug29807"},
7429 {".\\test\\foo", "test/foo"},
7430 {".\\test\\innodb_bug52663", "test/innodb_bug52663"},
7431 {".\\test\\t", "test/t"},
7432 {".\\test\\t1", "test/t1"},
7433 {".\\test\\t10", "test/t10"},
7434 {"C:\\a\\b\\db\\table", "db/table"},
7435 {"C:\\a\\b\\db\\\\\\\\\\\\\\table", "db/table"},
7436 {"C:\\a\\b\\\\\\\\db\\\\\\\\\\\\\\table", "db/table"},
7437 {"C:\\var\\tmp\\mysqld.1\\#sql842b_2_10", "mysqld.1/#sql842b_2_10"},
7438 {"db\\table", "db/table"},
7439 {"ddd\\t", "ddd/t"},
7440 {"d\\ttt", "d/ttt"},
7441 {"d\\t", "d/t"},
7442 };
7443
7444 for (size_t i = 0; i < UT_ARR_SIZE(test_data); i++) {
7445 printf(
7446 "test_normalize_table_name():"
7447 " testing \"%s\", expected \"%s\"... ",
7448 test_data[i][0], test_data[i][1]);
7449
7450 create_table_info_t::normalize_table_name(norm_name, test_data[i][0]);
7451
7452 if (strcmp(norm_name, test_data[i][1]) == 0) {
7453 printf("ok\n");
7454 } else {
7455 printf("got \"%s\"\n", norm_name);
7456 ut_error;
7457 }
7458 }
7459 }
7460
7461 /*********************************************************************
7462 Test ut_format_name(). */
7463 1 static void test_ut_format_name() {
7464 char buf[NAME_LEN * 3];
7465
7466 struct {
7467 const char *name;
7468 ulint buf_size;
7469 const char *expected;
7470 1 } test_data[] = {
7471 {"test/t1", sizeof(buf), "`test`.`t1`"},
7472 {"test/t1", 12, "`test`.`t1`"},
7473 {"test/t1", 11, "`test`.`t1"},
7474 {"test/t1", 10, "`test`.`t"},
7475 {"test/t1", 9, "`test`.`"},
7476 {"test/t1", 8, "`test`."},
7477 {"test/t1", 7, "`test`"},
7478 {"test/t1", 6, "`test"},
7479 {"test/t1", 5, "`tes"},
7480 {"test/t1", 4, "`te"},
7481 {"test/t1", 3, "`t"},
7482 {"test/t1", 2, "`"},
7483 {"test/t1", 1, ""},
7484 {"test/t1", 0, "BUF_NOT_CHANGED"},
7485 {"table", sizeof(buf), "`table`"},
7486 {"ta'le", sizeof(buf), "`ta'le`"},
7487 {"ta\"le", sizeof(buf), "`ta\"le`"},
7488 {"ta`le", sizeof(buf), "`ta``le`"},
7489 };
7490
7491
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 1 times.
19 for (size_t i = 0; i < UT_ARR_SIZE(test_data); i++) {
7492 18 memcpy(buf, "BUF_NOT_CHANGED", strlen("BUF_NOT_CHANGED") + 1);
7493
7494 char *ret;
7495
7496
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 ret = ut_format_name(test_data[i].name, buf, test_data[i].buf_size);
7497
7498
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 ut_a(ret == buf);
7499
7500
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (strcmp(buf, test_data[i].expected) == 0) {
7501
3/6
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
36 ib::info(ER_IB_MSG_550) << "ut_format_name(" << test_data[i].name
7502
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
18 << ", buf, " << test_data[i].buf_size
7503 << "),"
7504
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 " expected "
7505
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
18 << test_data[i].expected << ", OK";
7506 } else {
7507 ib::error(ER_IB_MSG_551)
7508 << "ut_format_name(" << test_data[i].name << ", buf, "
7509 << test_data[i].buf_size
7510 << "),"
7511 " expected "
7512 << test_data[i].expected << ", ERROR: got " << buf;
7513 ut_error;
7514 }
7515 }
7516 1 }
7517 #endif /* UNIV_DEBUG */
7518
7519 /** Match index columns between MySQL and InnoDB.
7520 This function checks whether the index column information
7521 is consistent between KEY info from mysql and that from innodb index.
7522 @param[in] key_info Index info from mysql
7523 @param[in] index_info Index info from InnoDB
7524 @return true if all column types match. */
7525 4055820 bool innobase_match_index_columns(const KEY *key_info,
7526 const dict_index_t *index_info) {
7527 const KEY_PART_INFO *key_part;
7528 const KEY_PART_INFO *key_end;
7529 const dict_field_t *innodb_idx_fld;
7530 const dict_field_t *innodb_idx_fld_end;
7531
7532
1/2
✓ Branch 0 taken 4055820 times.
✗ Branch 1 not taken.
4055820 DBUG_TRACE;
7533
7534 /* Check whether user defined index column count matches */
7535
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4055820 times.
4055820 if (key_info->user_defined_key_parts != index_info->n_user_defined_cols) {
7536 return false;
7537 }
7538
7539 4055820 key_part = key_info->key_part;
7540 4055820 key_end = key_part + key_info->user_defined_key_parts;
7541 4055820 innodb_idx_fld = index_info->fields;
7542 4055820 innodb_idx_fld_end = index_info->fields + index_info->n_fields;
7543
7544 /* Check each index column's datatype. We do not check
7545 column name because there exists case that index
7546 column name got modified in mysql but such change does not
7547 propagate to InnoDB.
7548 One hidden assumption here is that the index column sequences
7549 are matched up between those in mysql and InnoDB. */
7550
2/2
✓ Branch 0 taken 6851620 times.
✓ Branch 1 taken 4055820 times.
10907440 for (; key_part != key_end; ++key_part) {
7551 ulint col_type;
7552 ulint is_unsigned;
7553 6851620 ulint mtype = innodb_idx_fld->col->mtype;
7554
7555 /* Need to translate to InnoDB column type before
7556 comparison. */
7557
1/2
✓ Branch 0 taken 6851620 times.
✗ Branch 1 not taken.
6851620 col_type = get_innobase_type_from_mysql_type(&is_unsigned, key_part->field);
7558
7559 /* Ignore InnoDB specific system columns. */
7560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6851620 times.
6851620 while (mtype == DATA_SYS) {
7561 innodb_idx_fld++;
7562
7563 if (innodb_idx_fld >= innodb_idx_fld_end) {
7564 return false;
7565 }
7566 }
7567
7568 6851620 if ((bool)innodb_idx_fld->is_ascending !=
7569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6851620 times.
6851620 !(key_part->key_part_flag & HA_REVERSE_SORT)) {
7570 /* Column Type mismatches */
7571 return false;
7572 }
7573
7574
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6851620 times.
6851620 if (col_type != mtype) {
7575 /* If the col_type we get from mysql type is a geometry
7576 data type, we should check if mtype is a legacy type
7577 from 5.6, either upgraded to DATA_GEOMETRY or not.
7578 This is indeed not an accurate check, but should be
7579 safe, since DATA_BLOB would be upgraded once we create
7580 spatial index on it and we intend to use DATA_GEOMETRY
7581 for legacy GIS data types which are of var-length. */
7582 switch (col_type) {
7583 case DATA_POINT:
7584 case DATA_VAR_POINT:
7585 if (DATA_POINT_MTYPE(mtype) || mtype == DATA_GEOMETRY ||
7586 mtype == DATA_BLOB) {
7587 break;
7588 }
7589 [[fallthrough]];
7590 case DATA_GEOMETRY:
7591 if (mtype == DATA_BLOB) {
7592 break;
7593 }
7594 [[fallthrough]];
7595 default:
7596 /* Column type mismatches */
7597 return false;
7598 }
7599 }
7600
7601 6851620 innodb_idx_fld++;
7602 }
7603
7604 4055820 return true;
7605 4055820 }
7606
7607 /** Build a template for a base column for a virtual column
7608 @param[in] table MySQL TABLE
7609 @param[in] clust_index InnoDB clustered index
7610 @param[in] field field in MySQL table
7611 @param[in] col InnoDB column
7612 @param[in,out] templ template to fill
7613 @param[in] col_no field index for virtual col
7614 */
7615 97320 static void innobase_vcol_build_templ(const TABLE *table,
7616 const dict_index_t *clust_index,
7617 Field *field, const dict_col_t *col,
7618 mysql_row_templ_t *templ, ulint col_no) {
7619
2/2
✓ Branch 0 taken 52357 times.
✓ Branch 1 taken 44963 times.
97320 if (col->is_virtual()) {
7620 52357 templ->is_virtual = true;
7621 52357 templ->col_no = col_no;
7622 52357 templ->clust_rec_field_no = ULINT_UNDEFINED;
7623 52357 templ->rec_field_no = col->ind;
7624 } else {
7625 44963 templ->is_virtual = false;
7626 44963 templ->col_no = col_no;
7627 44963 templ->clust_rec_field_no = dict_col_get_clust_pos(col, clust_index);
7628
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44963 times.
44963 ut_a(templ->clust_rec_field_no != ULINT_UNDEFINED);
7629
7630 44963 templ->rec_field_no = templ->clust_rec_field_no;
7631 }
7632
7633 97320 templ->icp_rec_field_no = ULINT_UNDEFINED;
7634
7635
2/2
✓ Branch 0 taken 52225 times.
✓ Branch 1 taken 45095 times.
97320 if (field->is_nullable()) {
7636 52225 templ->mysql_null_byte_offset = field->null_offset();
7637
7638 52225 templ->mysql_null_bit_mask = (ulint)field->null_bit;
7639 } else {
7640 45095 templ->mysql_null_bit_mask = 0;
7641 }
7642
7643 97320 templ->mysql_col_offset = static_cast<ulint>(get_field_offset(table, field));
7644 97320 templ->mysql_col_len = static_cast<ulint>(field->pack_length());
7645 /* The multi-value index indexes attribute values in a JSON doc, so its
7646 index field length could be different from the actual column data length */
7647
6/6
✓ Branch 0 taken 52357 times.
✓ Branch 1 taken 44963 times.
✓ Branch 2 taken 582 times.
✓ Branch 3 taken 51775 times.
✓ Branch 4 taken 582 times.
✓ Branch 5 taken 96738 times.
97320 if (templ->is_virtual && innobase_is_multi_value_fld(field)) {
7648 582 templ->mysql_mvidx_len = static_cast<ulint>(field->key_length());
7649 582 templ->is_multi_val = true;
7650 } else {
7651 96738 templ->mysql_mvidx_len = 0;
7652 96738 templ->is_multi_val = false;
7653 }
7654
7655 97320 templ->type = col->mtype;
7656 97320 templ->mysql_type = static_cast<ulint>(field->type());
7657
7658
2/2
✓ Branch 0 taken 41596 times.
✓ Branch 1 taken 55724 times.
97320 if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
7659 41596 templ->mysql_length_bytes = field->get_length_bytes();
7660 }
7661
7662 97320 templ->charset = dtype_get_charset_coll(col->prtype);
7663 97320 templ->mbminlen = col->get_mbminlen();
7664 97320 templ->mbmaxlen = col->get_mbmaxlen();
7665 97320 templ->is_unsigned = col->prtype & DATA_UNSIGNED;
7666 97320 templ->compressed = (field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED);
7667 97320 templ->zip_dict_data = field->zip_dict_data;
7668 97320 }
7669
7670 /** Callback used by MySQL server layer to initialize
7671 the table virtual columns' template
7672 @param[in] table MySQL TABLE
7673 @param[in,out] ib_table InnoDB table */
7674 2 void innobase_build_v_templ_callback(const TABLE *table, void *ib_table) {
7675 2 const dict_table_t *t_table = static_cast<dict_table_t *>(ib_table);
7676
7677 2 innobase_build_v_templ(table, t_table, t_table->vc_templ, nullptr, true,
7678 nullptr);
7679 2 }
7680
7681 /** Build template for the virtual columns and their base columns. This
7682 is done when the table first opened.
7683 @param[in] table MySQL TABLE
7684 @param[in] ib_table InnoDB dict_table_t
7685 @param[in,out] s_templ InnoDB template structure
7686 @param[in] add_v new virtual columns added along with
7687 add index call
7688 @param[in] locked true if dict_sys mutex is held
7689 @param[in] share_tbl_name original MySQL table name */
7690 44950 void innobase_build_v_templ(const TABLE *table, const dict_table_t *ib_table,
7691 dict_vcol_templ_t *s_templ,
7692 const dict_add_v_col_t *add_v, bool locked,
7693 const char *share_tbl_name) {
7694 44950 ulint ncol = ib_table->n_cols - DATA_N_SYS_COLS;
7695 44950 ulint n_v_col = ib_table->n_v_cols;
7696 bool marker[REC_MAX_N_FIELDS];
7697
7698
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44950 times.
44950 ut_ad(ncol < REC_MAX_N_FIELDS);
7699
7700
2/2
✓ Branch 0 taken 166 times.
✓ Branch 1 taken 44784 times.
44950 if (add_v != nullptr) {
7701 166 n_v_col += add_v->n_v_col;
7702 }
7703
7704
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44950 times.
44950 ut_ad(n_v_col > 0);
7705
7706
2/2
✓ Branch 0 taken 1066 times.
✓ Branch 1 taken 43884 times.
44950 if (!locked) {
7707
1/2
✓ Branch 0 taken 1066 times.
✗ Branch 1 not taken.
1066 dict_sys_mutex_enter();
7708 }
7709
7710
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44950 times.
44950 if (s_templ->vtempl) {
7711 if (!locked) {
7712 dict_sys_mutex_exit();
7713 }
7714 return;
7715 }
7716
7717 44950 memset(marker, 0, sizeof(bool) * ncol);
7718
7719 44950 s_templ->vtempl = static_cast<mysql_row_templ_t **>(ut::zalloc_withkey(
7720 44950 UT_NEW_THIS_FILE_PSI_KEY, (ncol + n_v_col) * sizeof *s_templ->vtempl));
7721 44950 s_templ->n_col = ncol;
7722 44950 s_templ->n_v_col = n_v_col;
7723 44950 s_templ->rec_len = table->s->reclength;
7724 44950 s_templ->default_rec = static_cast<byte *>(
7725 44950 ut::malloc_withkey(UT_NEW_THIS_FILE_PSI_KEY, table->s->reclength));
7726 44950 memcpy(s_templ->default_rec, table->s->default_values, table->s->reclength);
7727
7728 /* Mark those columns could be base columns */
7729
2/2
✓ Branch 0 taken 52178 times.
✓ Branch 1 taken 44950 times.
97128 for (ulint i = 0; i < ib_table->n_v_cols; i++) {
7730
1/2
✓ Branch 0 taken 52178 times.
✗ Branch 1 not taken.
52178 const dict_v_col_t *vcol = dict_table_get_nth_v_col(ib_table, i);
7731
7732
2/2
✓ Branch 0 taken 51169 times.
✓ Branch 1 taken 52178 times.
103347 for (ulint j = 0; j < vcol->num_base; j++) {
7733 51169 ulint col_no = vcol->base_col[j]->ind;
7734 51169 marker[col_no] = true;
7735 }
7736 }
7737
7738
2/2
✓ Branch 0 taken 166 times.
✓ Branch 1 taken 44784 times.
44950 if (add_v) {
7739
2/2
✓ Branch 0 taken 179 times.
✓ Branch 1 taken 166 times.
345 for (ulint i = 0; i < add_v->n_v_col; i++) {
7740 179 const dict_v_col_t *vcol = &add_v->v_col[i];
7741
7742
2/2
✓ Branch 0 taken 216 times.
✓ Branch 1 taken 179 times.
395 for (ulint j = 0; j < vcol->num_base; j++) {
7743 216 ulint col_no = vcol->base_col[j]->ind;
7744 216 marker[col_no] = true;
7745 }
7746 }
7747 }
7748
7749 44950 ulint j = 0;
7750 44950 ulint z = 0;
7751
7752
1/2
✓ Branch 0 taken 44950 times.
✗ Branch 1 not taken.
44950 const dict_index_t *clust_index = ib_table->first_index();
7753
7754
2/2
✓ Branch 0 taken 267237 times.
✓ Branch 1 taken 44950 times.
312187 for (ulint i = 0; i < table->s->fields; i++) {
7755 267237 Field *field = table->field[i];
7756
7757 /* Build template for virtual columns */
7758
4/4
✓ Branch 0 taken 54683 times.
✓ Branch 1 taken 212554 times.
✓ Branch 2 taken 52357 times.
✓ Branch 3 taken 2326 times.
267237 if (innobase_is_v_fld(field)) {
7759 #ifdef UNIV_DEBUG
7760 const char *name;
7761
7762
2/2
✓ Branch 0 taken 179 times.
✓ Branch 1 taken 52178 times.
52357 if (z >= ib_table->n_v_def) {
7763 179 name = add_v->v_col_name[z - ib_table->n_v_def];
7764 } else {
7765
1/2
✓ Branch 0 taken 52178 times.
✗ Branch 1 not taken.
52178 name = dict_table_get_v_col_name(ib_table, z);
7766 }
7767
7768
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52357 times.
52357 ut_ad(!ut_strcmp(name, field->field_name));
7769 #endif
7770 const dict_v_col_t *vcol;
7771
7772
2/2
✓ Branch 0 taken 179 times.
✓ Branch 1 taken 52178 times.
52357 if (z >= ib_table->n_v_def) {
7773 179 vcol = &add_v->v_col[z - ib_table->n_v_def];
7774 } else {
7775
1/2
✓ Branch 0 taken 52178 times.
✗ Branch 1 not taken.
52178 vcol = dict_table_get_nth_v_col(ib_table, z);
7776 }
7777
7778 104714 s_templ->vtempl[z + s_templ->n_col] =
7779 52357 static_cast<mysql_row_templ_t *>(ut::malloc_withkey(
7780 52357 UT_NEW_THIS_FILE_PSI_KEY, sizeof *s_templ->vtempl[j]));
7781
7782 52357 innobase_vcol_build_templ(table, clust_index, field, &vcol->m_col,
7783
1/2
✓ Branch 0 taken 52357 times.
✗ Branch 1 not taken.
52357 s_templ->vtempl[z + s_templ->n_col], z);
7784 52357 z++;
7785 52357 continue;
7786 52357 }
7787
7788
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 214880 times.
214880 ut_ad(j < ncol);
7789
7790 /* Build template for base columns */
7791
2/2
✓ Branch 0 taken 44963 times.
✓ Branch 1 taken 169917 times.
214880 if (marker[j]) {
7792
1/2
✓ Branch 0 taken 44963 times.
✗ Branch 1 not taken.
44963 dict_col_t *col = ib_table->get_col(j);
7793
7794 #ifdef UNIV_DEBUG
7795
1/2
✓ Branch 0 taken 44963 times.
✗ Branch 1 not taken.
44963 const char *name = ib_table->get_col_name(j);
7796
7797
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44963 times.
44963 ut_ad(!ut_strcmp(name, field->field_name));
7798 #endif
7799
7800 44963 s_templ->vtempl[j] = static_cast<mysql_row_templ_t *>(ut::malloc_withkey(
7801 44963 UT_NEW_THIS_FILE_PSI_KEY, sizeof *s_templ->vtempl[j]));
7802
7803 44963 innobase_vcol_build_templ(table, clust_index, field, col,
7804
1/2
✓ Branch 0 taken 44963 times.
✗ Branch 1 not taken.
44963 s_templ->vtempl[j], j);
7805 }
7806
7807 214880 j++;
7808 }
7809
7810
2/2
✓ Branch 0 taken 1066 times.
✓ Branch 1 taken 43884 times.
44950 if (!locked) {
7811
1/2
✓ Branch 0 taken 1066 times.
✗ Branch 1 not taken.
1066 dict_sys_mutex_exit();
7812 }
7813
7814
1/2
✓ Branch 0 taken 44950 times.
✗ Branch 1 not taken.
44950 s_templ->db_name = table->s->db.str;
7815
1/2
✓ Branch 0 taken 44950 times.
✗ Branch 1 not taken.
44950 s_templ->tb_name = table->s->table_name.str;
7816
7817
2/2
✓ Branch 0 taken 42985 times.
✓ Branch 1 taken 1965 times.
44950 if (share_tbl_name) {
7818
1/2
✓ Branch 0 taken 42985 times.
✗ Branch 1 not taken.
42985 s_templ->share_name = share_tbl_name;
7819 }
7820 }
7821
7822 /** This function builds a translation table in INNOBASE_SHARE
7823 structure for fast index location with mysql array number from its
7824 table->key_info structure. This also provides the necessary translation
7825 between the key order in mysql key_info and InnoDB ib_table->indexes if
7826 they are not fully matched with each other.
7827 Note we do not have any mutex protecting the translation table
7828 building based on the assumption that there is no concurrent
7829 index creation/drop and DMLs that requires index lookup. All table
7830 handle will be closed before the index creation/drop.
7831 @return true if index translation table built successfully */
7832 4025299 bool innobase_build_index_translation(
7833 const TABLE *table, /*!< in: table in MySQL data
7834 dictionary */
7835 dict_table_t *ib_table, /*!< in: table in InnoDB data
7836 dictionary */
7837 INNOBASE_SHARE *share) /*!< in/out: share structure
7838 where index translation table
7839 will be constructed in. */
7840 {
7841
1/2
✓ Branch 0 taken 4025302 times.
✗ Branch 1 not taken.
4025299 DBUG_TRACE;
7842
7843 4025302 bool ret = true;
7844
7845
1/2
✓ Branch 0 taken 4025302 times.
✗ Branch 1 not taken.
4025302 dict_sys_mutex_enter();
7846
7847 4025302 ulint mysql_num_index = table->s->keys;
7848
1/2
✓ Branch 0 taken 4025302 times.
✗ Branch 1 not taken.
4025302 ulint ib_num_index = UT_LIST_GET_LEN(ib_table->indexes);
7849 4025302 dict_index_t **index_mapping = share->idx_trans_tbl.index_mapping;
7850
7851 /* If there exists inconsistency between MySQL and InnoDB dictionary
7852 (metadata) information, the number of index defined in MySQL
7853 could exceed that in InnoDB, do not build index translation
7854 table in such case */
7855
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4025302 times.
4025302 if (ib_num_index < mysql_num_index) {
7856 ret = false;
7857 goto func_exit;
7858 }
7859
7860 /* If index entry count is non-zero, nothing has
7861 changed since last update, directly return true */
7862
2/2
✓ Branch 0 taken 2032850 times.
✓ Branch 1 taken 1992452 times.
4025302 if (share->idx_trans_tbl.index_count) {
7863 /* Index entry count should still match mysql_num_index */
7864
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2032850 times.
2032850 ut_a(share->idx_trans_tbl.index_count == mysql_num_index);
7865 2032850 goto func_exit;
7866 }
7867
7868 /* The number of index increased, rebuild the mapping table */
7869
2/2
✓ Branch 0 taken 1597665 times.
✓ Branch 1 taken 394787 times.
1992452 if (mysql_num_index > share->idx_trans_tbl.array_size) {
7870 index_mapping = reinterpret_cast<dict_index_t **>(
7871 1597665 ut::realloc_withkey(UT_NEW_THIS_FILE_PSI_KEY, index_mapping,
7872 mysql_num_index * sizeof(*index_mapping)));
7873
7874
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1597665 times.
1597665 if (index_mapping == nullptr) {
7875 /* Report an error if index_mapping continues to be
7876 NULL and mysql_num_index is a non-zero value */
7877 log_errlog(ERROR_LEVEL, ER_INNODB_TRX_XLATION_TABLE_OOM, mysql_num_index,
7878 share->idx_trans_tbl.array_size);
7879 ret = false;
7880 goto func_exit;
7881 }
7882
7883 1597665 share->idx_trans_tbl.array_size = mysql_num_index;
7884 }
7885
7886 /* For each index in the mysql key_info array, fetch its
7887 corresponding InnoDB index pointer into index_mapping
7888 array. */
7889
2/2
✓ Branch 0 taken 3999200 times.
✓ Branch 1 taken 1992452 times.
5991652 for (ulint count = 0; count < mysql_num_index; count++) {
7890 /* Fetch index pointers into index_mapping according to mysql
7891 index sequence */
7892 7998400 index_mapping[count] =
7893
1/2
✓ Branch 0 taken 3999200 times.
✗ Branch 1 not taken.
3999200 dict_table_get_index_on_name(ib_table, table->key_info[count].name);
7894
7895
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3999200 times.
3999200 if (index_mapping[count] == nullptr) {
7896 log_errlog(ERROR_LEVEL, ER_INNODB_CANT_FIND_INDEX_IN_INNODB_DD,
7897 table->key_info[count].name);
7898 ret = false;
7899 goto func_exit;
7900 }
7901
7902 /* Double check fetched index has the same
7903 column info as those in mysql key_info. */
7904
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3999200 times.
3999200 if (!innobase_match_index_columns(&table->key_info[count],
7905
1/2
✓ Branch 0 taken 3999200 times.
✗ Branch 1 not taken.
3999200 index_mapping[count])) {
7906 log_errlog(ERROR_LEVEL, ER_INNODB_INDEX_COLUMN_INFO_UNLIKE_MYSQLS,
7907 table->key_info[count].name);
7908 ret = false;
7909 goto func_exit;
7910 }
7911 }
7912
7913 /* Successfully built the translation table */
7914 1992452 share->idx_trans_tbl.index_count = mysql_num_index;
7915
7916 4025302 func_exit:
7917
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4025302 times.
4025302 if (!ret) {
7918 /* Build translation table failed. */
7919 ut::free(index_mapping);
7920
7921 share->idx_trans_tbl.array_size = 0;
7922 share->idx_trans_tbl.index_count = 0;
7923 index_mapping = nullptr;
7924 }
7925
7926 4025302 share->idx_trans_tbl.index_mapping = index_mapping;
7927
7928
1/2
✓ Branch 0 taken 4025302 times.
✗ Branch 1 not taken.
4025302 dict_sys_mutex_exit();
7929
7930 4025302 return ret;
7931 4025302 }
7932
7933 /** This function uses index translation table to quickly locate the
7934 requested index structure.
7935 Note we do not have mutex protection for the index translatoin table
7936 access, it is based on the assumption that there is no concurrent
7937 translation table rebuild (fter create/drop index) and DMLs that
7938 require index lookup.
7939 @return dict_index_t structure for requested index. NULL if
7940 fail to locate the index structure. */
7941 132327353 static dict_index_t *innobase_index_lookup(
7942 INNOBASE_SHARE *share, /*!< in: share structure for index
7943 translation table. */
7944 uint keynr) /*!< in: index number for the requested
7945 index */
7946 {
7947
1/2
✓ Branch 0 taken 132327419 times.
✗ Branch 1 not taken.
132327353 if (share->idx_trans_tbl.index_mapping == nullptr ||
7948
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 132327736 times.
132327419 keynr >= share->idx_trans_tbl.index_count) {
7949 return (nullptr);
7950 }
7951
7952 132327736 return (share->idx_trans_tbl.index_mapping[keynr]);
7953 }
7954
7955 /** Set the autoinc column max value. This should only be called from
7956 ha_innobase::open, therefore there's no need for a covering lock. */
7957 109574 void ha_innobase::innobase_initialize_autoinc() {
7958 ulonglong auto_inc;
7959 109574 const Field *field = table->found_next_number_field;
7960
7961
1/2
✓ Branch 0 taken 109574 times.
✗ Branch 1 not taken.
109574 if (field != nullptr) {
7962 109574 auto_inc = field->get_max_int_value();
7963
7964 /* autoinc column cannot be virtual column */
7965
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 109574 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 109574 times.
109574 ut_ad(!innobase_is_v_fld(field));
7966 } else {
7967 /* We have no idea what's been passed in to us as the
7968 autoinc column. We set it to the 0, effectively disabling
7969 updates to the table. */
7970 auto_inc = 0;
7971
7972 ib::info(ER_IB_MSG_552) << "Unable to determine the AUTOINC column name";
7973 }
7974
7975
2/2
✓ Branch 0 taken 91 times.
✓ Branch 1 taken 109483 times.
109574 if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
7976 /* If the recovery level is set so high that writes
7977 are disabled we force the AUTOINC counter to 0
7978 value effectively disabling writes to the table.
7979 Secondly, we avoid reading the table in case the read
7980 results in failure due to a corrupted table/index.
7981
7982 We will not return an error to the client, so that the
7983 tables can be dumped with minimal hassle. If an error
7984 were returned in this case, the first attempt to read
7985 the table would fail and subsequent SELECTs would succeed. */
7986 91 auto_inc = 0;
7987
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 109483 times.
109483 } else if (field == nullptr) {
7988 /* This is a far more serious error, best to avoid
7989 opening the table and return failure. */
7990 my_error(ER_AUTOINC_READ_FAILED, MYF(0));
7991 } else {
7992 109483 dict_index_t *index = nullptr;
7993 const char *col_name;
7994 uint64_t read_auto_inc;
7995 ulint err;
7996
7997
2/4
✓ Branch 0 taken 109483 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 109483 times.
✗ Branch 3 not taken.
109483 update_thd(ha_thd());
7998
7999 109483 col_name = field->field_name;
8000
8001
1/2
✓ Branch 0 taken 109483 times.
✗ Branch 1 not taken.
109483 read_auto_inc = dict_table_autoinc_read(m_prebuilt->table);
8002
8003
2/2
✓ Branch 0 taken 23872 times.
✓ Branch 1 taken 85611 times.
109483 if (read_auto_inc == 0) {
8004
1/2
✓ Branch 0 taken 23872 times.
✗ Branch 1 not taken.
23872 index = innobase_get_index(table->s->next_number_index);
8005
8006 /* Execute SELECT MAX(col_name) FROM TABLE;
8007 This is necessary when an imported tablespace
8008 doesn't have a correct cfg file so autoinc
8009 has not been initialized, or the table is empty. */
8010
1/2
✓ Branch 0 taken 23872 times.
✗ Branch 1 not taken.
23872 err = row_search_max_autoinc(index, col_name, &read_auto_inc);
8011
8012
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23872 times.
23872 if (read_auto_inc > 0) {
8013 ib::warn(ER_IB_MSG_553)
8014 << "Reading max(auto_inc_col) = " << read_auto_inc << " for table "
8015 << index->table->name << ", because there was an IMPORT"
8016 << " without cfg file.";
8017 }
8018
8019 } else {
8020 85611 err = DB_SUCCESS;
8021 }
8022
8023
1/3
✓ Branch 0 taken 109483 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
109483 switch (err) {
8024 109483 case DB_SUCCESS: {
8025 ulonglong col_max_value;
8026
8027
1/2
✓ Branch 0 taken 109483 times.
✗ Branch 1 not taken.
109483 col_max_value = field->get_max_int_value();
8028
8029 /* At the this stage we do not know the increment
8030 nor the offset, so use a default increment of 1. */
8031
8032
1/2
✓ Branch 0 taken 109483 times.
✗ Branch 1 not taken.
109483 auto_inc = innobase_next_autoinc(read_auto_inc, 1, 1, 0, col_max_value);
8033
8034 109483 break;
8035 }
8036 case DB_RECORD_NOT_FOUND:
8037 ib::error(ER_IB_MSG_554) << "MySQL and InnoDB data dictionaries are"
8038 " out of sync. Unable to find the AUTOINC"
8039 " column "
8040 << col_name
8041 << " in the InnoDB"
8042 " table "
8043 << index->table->name
8044 << ". We set"
8045 " the next AUTOINC column value to 0, in"
8046 " effect disabling the AUTOINC next value"
8047 " generation.";
8048
8049 ib::info(ER_IB_MSG_555) << "You can either set the next AUTOINC"
8050 " value explicitly using ALTER TABLE or fix"
8051 " the data dictionary by recreating the"
8052 " table.";
8053
8054 /* This will disable the AUTOINC generation. */
8055 auto_inc = 0;
8056
8057 /* We want the open to succeed, so that the user can
8058 take corrective action. ie. reads should succeed but
8059 updates should fail. */
8060 err = DB_SUCCESS;
8061 break;
8062 default:
8063 /* row_search_max_autoinc() should only return
8064 one of DB_SUCCESS or DB_RECORD_NOT_FOUND. */
8065 ut_error;
8066 }
8067 }
8068
8069 109574 dict_table_autoinc_initialize(m_prebuilt->table, auto_inc);
8070 109574 }
8071
8072 /** Open an InnoDB table.
8073 @param[in] name table name
8074 @param[in] open_flags flags for opening table from SQL-layer.
8075 @param[in] table_def dd::Table object describing table to be opened
8076 @retval 1 if error
8077 @retval 0 if success */
8078 4025379 int ha_innobase::open(const char *name, int, uint open_flags,
8079 const dd::Table *table_def) {
8080 dict_table_t *ib_table;
8081 char norm_name[FN_REFLEN];
8082 THD *thd;
8083 4025379 bool cached = false;
8084
8085
1/2
✓ Branch 0 taken 4025399 times.
✗ Branch 1 not taken.
4025379 DBUG_TRACE;
8086
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4025399 times.
4025399 assert(table_share == table->s);
8087
8088
1/2
✓ Branch 0 taken 4025391 times.
✗ Branch 1 not taken.
4025399 thd = ha_thd();
8089
8090
2/4
✓ Branch 0 taken 4025391 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4025391 times.
4025391 if (!normalize_table_name(norm_name, name)) {
8091 /* purecov: begin inspected */
8092 ut_d(ut_error);
8093 ut_o(return (HA_ERR_TOO_LONG_PATH));
8094 /* purecov: end */
8095 }
8096
8097 4025391 m_user_thd = nullptr;
8098 4025391 m_share = nullptr;
8099
8100 /* Will be allocated if it is needed in ::update_row() */
8101 4025391 m_upd_buf = nullptr;
8102 4025391 m_upd_buf_size = 0;
8103
8104 /* Get pointer to a table object in InnoDB dictionary cache.
8105 For intrinsic table, get it from session private data */
8106
2/4
✓ Branch 0 taken 4025395 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4025388 times.
✗ Branch 3 not taken.
4025391 ib_table = thd_to_innodb_session(thd)->lookup_table_handler(norm_name);
8107
8108
2/2
✓ Branch 0 taken 3914192 times.
✓ Branch 1 taken 111196 times.
4025388 if (ib_table == nullptr) {
8109
3/4
✓ Branch 0 taken 3785942 times.
✓ Branch 1 taken 128250 times.
✓ Branch 2 taken 3785947 times.
✗ Branch 3 not taken.
3914192 DEBUG_SYNC_C("ha_innobase_open");
8110
8111
1/2
✓ Branch 0 taken 3914202 times.
✗ Branch 1 not taken.
3914197 dict_sys_mutex_enter();
8112
1/2
✓ Branch 0 taken 3914202 times.
✗ Branch 1 not taken.
3914202 ib_table = dict_table_check_if_in_cache_low(norm_name);
8113
2/2
✓ Branch 0 taken 3194749 times.
✓ Branch 1 taken 719453 times.
3914202 if (ib_table != nullptr) {
8114
3/4
✓ Branch 0 taken 3194749 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3194747 times.
3194749 if (ib_table->is_corrupted()) {
8115 /* Optionally remove this corrupted table from cache now
8116 if no other thread is still using it. If not, the corrupted bit
8117 will keep it from being used.*/
8118
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (ib_table->get_ref_count() == 0) {
8119
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 dict_table_remove_from_cache(ib_table);
8120 }
8121 2 ib_table = nullptr;
8122 2 cached = true;
8123
2/2
✓ Branch 0 taken 7120 times.
✓ Branch 1 taken 3187627 times.
3194747 } else if (ib_table->refresh_fk) {
8124
1/2
✓ Branch 0 taken 7120 times.
✗ Branch 1 not taken.
7120 ib_table->acquire_with_lock();
8125
8126
1/2
✓ Branch 0 taken 7120 times.
✗ Branch 1 not taken.
7120 dict_names_t fk_tables;
8127
1/2
✓ Branch 0 taken 7120 times.
✗ Branch 1 not taken.
7120 dict_sys_mutex_exit();
8128
1/2
✓ Branch 0 taken 7120 times.
✗ Branch 1 not taken.
7120 dd::cache::Dictionary_client *client = dd::get_dd_client(thd);
8129
1/2
✓ Branch 0 taken 7120 times.
✗ Branch 1 not taken.
7120 dd::cache::Dictionary_client::Auto_releaser releaser(client);
8130
8131 21360 dberr_t err = dd_table_load_fk(
8132
1/2
✓ Branch 0 taken 7120 times.
✗ Branch 1 not taken.
7120 client, ib_table->name.m_name, nullptr, ib_table,
8133 7120 &table_def->table(), thd, false,
8134
1/2
✓ Branch 0 taken 7120 times.
✗ Branch 1 not taken.
7120 !thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS), &fk_tables);
8135
8136
1/2
✓ Branch 0 taken 7120 times.
✗ Branch 1 not taken.
7120 dict_sys_mutex_enter();
8137 7120 ib_table->refresh_fk = false;
8138
8139
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7120 times.
7120 if (err != DB_SUCCESS) {
8140 ib_table->release();
8141 goto reload;
8142 }
8143
8144 7120 cached = true;
8145
4/6
✓ Branch 0 taken 7120 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7120 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 31075 times.
✓ Branch 5 taken 3156552 times.
3194747 } else if (ib_table->discard_after_ddl) {
8146 31075 reload:
8147
1/2
✓ Branch 0 taken 31075 times.
✗ Branch 1 not taken.
31075 btr_drop_ahi_for_table(ib_table);
8148
1/2
✓ Branch 0 taken 31075 times.
✗ Branch 1 not taken.
31075 dict_table_remove_from_cache(ib_table);
8149 31075 ib_table = nullptr;
8150 } else {
8151 3156552 cached = true;
8152
2/4
✓ Branch 0 taken 3156552 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3156552 times.
3156552 if (!dd_table_match(ib_table, table_def)) {
8153 dict_set_corrupted(ib_table->first_index());
8154 dict_table_remove_from_cache(ib_table);
8155 ib_table = nullptr;
8156 } else {
8157
1/2
✓ Branch 0 taken 3156552 times.
✗ Branch 1 not taken.
3156552 ib_table->acquire_with_lock();
8158 }
8159 }
8160
8161 /* If the table is in-memory, always get the latest
8162 version, in case this is open table after DDL */
8163
4/4
✓ Branch 0 taken 3163672 times.
✓ Branch 1 taken 31077 times.
✓ Branch 2 taken 2964246 times.
✓ Branch 3 taken 199426 times.
3194749 if (ib_table != nullptr && table_def != nullptr) {
8164
1/2
✓ Branch 0 taken 2964246 times.
✗ Branch 1 not taken.
2964246 ib_table->version = dd_get_version(table_def);
8165 }
8166
8167
2/2
✓ Branch 0 taken 3163672 times.
✓ Branch 1 taken 31077 times.
3194749 if (ib_table != nullptr) {
8168
1/2
✓ Branch 0 taken 3163672 times.
✗ Branch 1 not taken.
3163672 dict_table_ddl_release(ib_table);
8169 }
8170 }
8171
8172
1/2
✓ Branch 0 taken 3914202 times.
✗ Branch 1 not taken.
3914202 dict_sys_mutex_exit();
8173
8174
2/2
✓ Branch 0 taken 750528 times.
✓ Branch 1 taken 3163674 times.
3914202 if (!cached) {
8175
1/2
✓ Branch 0 taken 750528 times.
✗ Branch 1 not taken.
750528 dd::cache::Dictionary_client *client = dd::get_dd_client(thd);
8176
1/2
✓ Branch 0 taken 750528 times.
✗ Branch 1 not taken.
750528 dd::cache::Dictionary_client::Auto_releaser releaser(client);
8177
8178
1/2
✓ Branch 0 taken 750528 times.
✗ Branch 1 not taken.
750528 ib_table = dd_open_table(client, table, norm_name, table_def, thd);
8179
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 750526 times.
750528 if (!ib_table) {
8180
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 set_my_errno(ENOENT);
8181 2 return HA_ERR_NO_SUCH_TABLE;
8182 }
8183
2/2
✓ Branch 0 taken 750526 times.
✓ Branch 1 taken 2 times.
750528 }
8184 } else {
8185
1/2
✓ Branch 0 taken 111198 times.
✗ Branch 1 not taken.
111196 ib_table->acquire();
8186
2/4
✓ Branch 0 taken 111198 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 111198 times.
111198 ut_ad(ib_table->is_intrinsic());
8187 }
8188
8189
2/2
✓ Branch 0 taken 4025395 times.
✓ Branch 1 taken 3 times.
4025398 if (ib_table != nullptr) {
8190 /* Make sure table->is_dd_table is set */
8191 4025395 std::string db_str;
8192 4025396 std::string tbl_str;
8193
2/4
✓ Branch 0 taken 4025396 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4025396 times.
✗ Branch 3 not taken.
4025396 dict_name::get_table(ib_table->name.m_name, db_str, tbl_str);
8194
8195 4025396 ib_table->is_dd_table =
8196
4/8
✓ Branch 0 taken 4025396 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4025396 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4025396 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4025396 times.
✗ Branch 7 not taken.
4025396 dd::get_dictionary()->is_dd_table_name(db_str.c_str(), tbl_str.c_str());
8197 4025396 }
8198
8199 /* m_share might hold pointers to dict table indexes without any pin.
8200 We must always allocate m_share after opening the dict_table_t object
8201 and free it before de-allocating dict_table_t to avoid race. */
8202
2/2
✓ Branch 0 taken 4025396 times.
✓ Branch 1 taken 3 times.
4025399 if (ib_table != nullptr) {
8203
1/2
✓ Branch 0 taken 4025396 times.
✗ Branch 1 not taken.
4025396 m_share = get_share(name);
8204
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4025396 times.
4025396 if (m_share == nullptr) {
8205 dict_table_close(ib_table, false, false);
8206 return HA_ERR_SE_OUT_OF_MEMORY;
8207 }
8208
8209
3/10
✗ Branch 0 not taken.
✓ Branch 1 taken 4025396 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4025396 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 4025396 times.
4025396 if (UNIV_UNLIKELY(m_share->ib_table && m_share->ib_table->is_corrupt &&
8210 srv_pass_corrupt_table <= 1)) {
8211 free_share_and_nullify(&m_share);
8212 dict_table_close(ib_table, false, false);
8213 return HA_ERR_CRASHED_ON_USAGE;
8214 }
8215 }
8216
8217
3/4
✓ Branch 0 taken 4025396 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4025398 times.
8050794 if (ib_table != nullptr &&
8218
2/2
✓ Branch 0 taken 4024192 times.
✓ Branch 1 taken 1204 times.
4025396 ((!DICT_TF2_FLAG_IS_SET(ib_table, DICT_TF2_FTS_HAS_DOC_ID) &&
8219
4/6
✓ Branch 0 taken 4024192 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4024193 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1204 times.
✓ Branch 5 taken 4024192 times.
8049588 table->s->fields != dict_table_get_n_tot_u_cols(ib_table)) ||
8220 4025397 (DICT_TF2_FLAG_IS_SET(ib_table, DICT_TF2_FTS_HAS_DOC_ID) &&
8221
3/4
✓ Branch 0 taken 1204 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1203 times.
1204 (table->s->fields != dict_table_get_n_tot_u_cols(ib_table) - 1)))) {
8222 ib::warn(ER_IB_MSG_556)
8223 << "Table " << norm_name << " contains " << ib_table->get_n_user_cols()
8224 << " user"
8225 " defined columns in InnoDB, but "
8226 << table->s->fields
8227 << " columns in MySQL. Please check"
8228 " INFORMATION_SCHEMA.INNODB_COLUMNS and " REFMAN
8229 "innodb-troubleshooting.html for how to resolve the"
8230 " issue.";
8231
8232 /* Mark this table as corrupted, so the drop table
8233 or force recovery can still use it, but not others. */
8234 ib_table->first_index()->type |= DICT_CORRUPT;
8235 free_share_and_nullify(&m_share);
8236 dict_table_close(ib_table, false, false);
8237 ib_table = nullptr;
8238 }
8239
8240
5/10
✓ Branch 0 taken 4025396 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4025396 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4025398 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 4025398 times.
4025398 if (UNIV_UNLIKELY(ib_table && ib_table->is_corrupt &&
8241 srv_pass_corrupt_table <= 1)) {
8242 free_share_and_nullify(&m_share);
8243 dict_table_close(ib_table, false, false);
8244 return HA_ERR_CRASHED_ON_USAGE;
8245 }
8246
8247 8050787 FilSpace space;
8248
4/6
✓ Branch 0 taken 4025396 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4025396 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4025396 times.
✗ Branch 5 not taken.
4025398 if (ib_table) space = fil_space_acquire_silent(ib_table->space);
8249
8250 /* For encrypted table, check if the encryption info in data
8251 file can't be retrieved properly, mark it as corrupted. */
8252 8050794 if (ib_table != nullptr &&
8253
3/4
✓ Branch 0 taken 4025396 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4016917 times.
✓ Branch 3 taken 8479 times.
4025396 (dd_is_table_in_encrypted_tablespace(ib_table) ||
8254
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4016917 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4016917 (ib_table->keyring_encryption_info.page0_has_crypt_data &&
8255 ib_table->keyring_encryption_info.is_encryption_in_progress())) &&
8256
8/8
✓ Branch 0 taken 4025396 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 57 times.
✓ Branch 3 taken 8422 times.
✓ Branch 4 taken 53 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 53 times.
✓ Branch 7 taken 4025345 times.
8050794 ib_table->ibd_file_missing && !dict_table_is_discarded(ib_table)) {
8257 /* Mark this table as corrupted, so the drop table
8258 or force recovery can still use it, but not others. */
8259 53 FilSpace space;
8260 53 int error = 0;
8261
3/6
✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 53 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 53 times.
✗ Branch 5 not taken.
53 if (ib_table) space = fil_space_acquire_silent(ib_table->space);
8262
2/4
✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 53 times.
106 if (space() == NULL &&
8263
1/2
✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
53 (ib_table->keyring_encryption_info.keyring_encryption_key_is_missing ||
8264
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 ib_table->keyring_encryption_info.page0_has_crypt_data)) {
8265 /* Proper error message has been already printed by
8266 * Datafile::validate_first_page, thus we do not print anything here */
8267 error = HA_ERR_ENCRYPTION_KEY_MISSING;
8268 } else {
8269
1/2
✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
53 my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0));
8270 53 error = HA_ERR_TABLE_CORRUPT;
8271 }
8272
1/2
✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
53 dict_table_close(ib_table, false, false);
8273 53 ib_table = nullptr;
8274
8275
1/2
✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
53 free_share_and_nullify(&m_share);
8276 53 return error;
8277 53 }
8278
8279
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4025343 times.
4025345 if (nullptr == ib_table) {
8280
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 ib::warn(ER_IB_MSG_557)
8281
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 << "Cannot open table " << norm_name << TROUBLESHOOTING_MSG;
8282
8283
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 set_my_errno(ENOENT);
8284
8285 2 return HA_ERR_NO_SUCH_TABLE;
8286 }
8287
8288
1/2
✓ Branch 0 taken 4025342 times.
✗ Branch 1 not taken.
4025343 innobase_copy_frm_flags_from_table_share(ib_table, table->s);
8289
8290
1/2
✓ Branch 0 taken 4025343 times.
✗ Branch 1 not taken.
4025342 dict_stats_init(ib_table);
8291
8292 4025343 MONITOR_INC(MONITOR_TABLE_OPEN);
8293
8294 bool no_tablespace;
8295
8296
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 4025294 times.
4025343 if (dict_table_is_discarded(ib_table)) {
8297 /* If the op is an IMPORT, open the space without this warning. */
8298
3/4
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 9 times.
49 if (thd_tablespace_op(thd) != Alter_info::ALTER_IMPORT_TABLESPACE) {
8299 40 ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_TABLESPACE_DISCARDED,
8300
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 table->s->table_name.str);
8301 }
8302
8303 /* Allow an open because a proper DISCARD should have set
8304 all the flags and index root page numbers to FIL_NULL that
8305 should prevent any DML from running but it should allow DDL
8306 operations. */
8307 49 no_tablespace = false;
8308
8309
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 4025246 times.
4025294 } else if (ib_table->ibd_file_missing) {
8310
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_TABLESPACE_MISSING, norm_name);
8311
8312 /* This means we have no idea what happened to the tablespace
8313 file, best to play it safe. */
8314
8315 48 no_tablespace = true;
8316 } else {
8317 4025246 no_tablespace = false;
8318 }
8319
8320
7/8
✓ Branch 0 taken 4025343 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4025199 times.
✓ Branch 3 taken 144 times.
✓ Branch 4 taken 47 times.
✓ Branch 5 taken 4025152 times.
✓ Branch 6 taken 47 times.
✓ Branch 7 taken 4025296 times.
4025343 if (!thd_tablespace_op(thd) && no_tablespace) {
8321
1/2
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
47 free_share_and_nullify(&m_share);
8322
1/2
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
47 set_my_errno(ENOENT);
8323
8324
1/2
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
47 dict_table_close(ib_table, false, false);
8325
8326 47 return HA_ERR_TABLESPACE_MISSING;
8327 }
8328
8329
1/2
✓ Branch 0 taken 4025279 times.
✗ Branch 1 not taken.
4025296 m_prebuilt = row_create_prebuilt(ib_table, table->s->reclength);
8330
8331 4025279 m_prebuilt->default_rec = table->s->default_values;
8332
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4025296 times.
4025279 ut_ad(m_prebuilt->default_rec);
8333
8334 4025296 m_prebuilt->m_mysql_table = table;
8335 4025296 m_prebuilt->m_mysql_handler = this;
8336
8337
3/4
✓ Branch 0 taken 4025296 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 111198 times.
✓ Branch 3 taken 3914098 times.
4025296 if (ib_table->is_intrinsic()) {
8338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 111198 times.
111198 ut_ad(open_flags & HA_OPEN_INTERNAL_TABLE);
8339
8340
1/2
✓ Branch 0 taken 111198 times.
✗ Branch 1 not taken.
111198 m_prebuilt->m_temp_read_shared = table_share->ref_count() >= 2;
8341
8342
2/2
✓ Branch 0 taken 336 times.
✓ Branch 1 taken 110862 times.
111198 if (m_prebuilt->m_temp_read_shared) {
8343
2/2
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 224 times.
336 if (ib_table->temp_prebuilt == nullptr) {
8344 112 ib_table->temp_prebuilt =
8345
1/2
✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
112 ut::new_withkey<temp_prebuilt_vec>(UT_NEW_THIS_FILE_PSI_KEY);
8346 }
8347
8348
1/2
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
336 ib_table->temp_prebuilt->push_back(m_prebuilt);
8349 }
8350 111198 m_prebuilt->m_temp_tree_modified = false;
8351 }
8352
8353 4025296 key_used_on_scan = table_share->primary_key;
8354
8355
2/2
✓ Branch 0 taken 43273 times.
✓ Branch 1 taken 3982023 times.
4025296 if (ib_table->n_v_cols) {
8356
1/2
✓ Branch 0 taken 43273 times.
✗ Branch 1 not taken.
43273 dict_sys_mutex_enter();
8357
2/2
✓ Branch 0 taken 22619 times.
✓ Branch 1 taken 20654 times.
43273 if (ib_table->vc_templ == nullptr) {
8358 22619 ib_table->vc_templ =
8359
1/2
✓ Branch 0 taken 22619 times.
✗ Branch 1 not taken.
22619 ut::new_withkey<dict_vcol_templ_t>(UT_NEW_THIS_FILE_PSI_KEY);
8360 22619 ib_table->vc_templ->vtempl = nullptr;
8361
2/2
✓ Branch 0 taken 19870 times.
✓ Branch 1 taken 784 times.
20654 } else if (ib_table->get_ref_count() == 1) {
8362 /* Clean and refresh the template if no one else
8363 get hold on it */
8364
1/2
✓ Branch 0 taken 19870 times.
✗ Branch 1 not taken.
19870 dict_free_vc_templ(ib_table->vc_templ);
8365 19870 ib_table->vc_templ->vtempl = nullptr;
8366 }
8367
8368
2/2
✓ Branch 0 taken 42489 times.
✓ Branch 1 taken 784 times.
43273 if (ib_table->vc_templ->vtempl == nullptr) {
8369 42489 innobase_build_v_templ(table, ib_table, ib_table->vc_templ, nullptr, true,
8370
1/2
✓ Branch 0 taken 42489 times.
✗ Branch 1 not taken.
42489 m_share->table_name);
8371 }
8372
8373
1/2
✓ Branch 0 taken 43273 times.
✗ Branch 1 not taken.
43273 dict_sys_mutex_exit();
8374 }
8375
8376
2/4
✓ Branch 0 taken 4025296 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4025296 times.
4025296 if (!innobase_build_index_translation(table, ib_table, m_share)) {
8377 log_errlog(ERROR_LEVEL, ER_INNODB_CANT_BUILD_INDEX_XLATION_TABLE_FOR, name);
8378 }
8379
8380 /* Allocate a buffer for a 'row reference'. A row reference is
8381 a string of bytes of length ref_length which uniquely specifies
8382 a row in our table. Note that MySQL may also compare two row
8383 references for equality by doing a simple memcmp on the strings
8384 of length ref_length! */
8385
8386
3/4
✓ Branch 0 taken 4025296 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3398836 times.
✓ Branch 3 taken 626460 times.
4025296 if (!row_table_got_default_clust_index(ib_table)) {
8387 3398836 m_prebuilt->clust_index_was_generated = false;
8388
8389
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3398836 times.
3398836 if (table_share->is_missing_primary_key()) {
8390 log_errlog(ERROR_LEVEL, ER_INNODB_PK_NOT_IN_MYSQL, name);
8391
8392 /* This mismatch could cause further problems
8393 if not attended, bring this to the user's attention
8394 by printing a warning in addition to log a message
8395 in the errorlog */
8396 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_NO_SUCH_INDEX,
8397 "InnoDB: Table %s has a"
8398 " primary key in InnoDB data"
8399 " dictionary, but not in"
8400 " MySQL!",
8401 name);
8402
8403 /* If table_share->is_missing_primary_key(),
8404 the table_share->primary_key
8405 value could be out of bound if continue to index
8406 into key_info[] array. Find InnoDB primary index,
8407 and assign its key_length to ref_length.
8408 In addition, since MySQL indexes are sorted starting
8409 with primary index, unique index etc., initialize
8410 ref_length to the first index key length in
8411 case we fail to find InnoDB cluster index.
8412
8413 Please note, this will not resolve the primary
8414 index mismatch problem, other side effects are
8415 possible if users continue to use the table.
8416 However, we allow this table to be opened so
8417 that user can adopt necessary measures for the
8418 mismatch while still being accessible to the table
8419 date. */
8420 if (!table->key_info) {
8421 ut_ad(!table->s->keys);
8422 ref_length = 0;
8423 } else {
8424 ref_length = table->key_info[0].key_length;
8425 }
8426
8427 /* Find corresponding cluster index
8428 key length in MySQL's key_info[] array */
8429 for (uint i = 0; i < table->s->keys; i++) {
8430 dict_index_t *index;
8431 index = innobase_get_index(i);
8432 if (index->is_clustered()) {
8433 ref_length = table->key_info[i].key_length;
8434 }
8435 }
8436 } else {
8437 /* MySQL allocates the buffer for ref.
8438 key_info->key_length includes space for all key
8439 columns + one byte for each column that may be
8440 NULL. ref_length must be as exact as possible to
8441 save space, because all row reference buffers are
8442 allocated based on ref_length. */
8443
8444 3398836 ref_length = table->key_info[table_share->primary_key].key_length;
8445 }
8446 } else {
8447
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 626460 times.
626460 if (!table_share->is_missing_primary_key()) {
8448 log_errlog(ERROR_LEVEL, ER_INNODB_PK_ONLY_IN_MYSQL, name);
8449
8450 /* This mismatch could cause further problems
8451 if not attended, bring this to the user attention
8452 by printing a warning in addition to log a message
8453 in the errorlog */
8454 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_NO_SUCH_INDEX,
8455 "InnoDB: Table %s has no"
8456 " primary key in InnoDB data"
8457 " dictionary, but has one in"
8458 " MySQL!",
8459 name);
8460 }
8461
8462 626460 m_prebuilt->clust_index_was_generated = true;
8463
8464 626460 ref_length = DATA_ROW_ID_LEN;
8465
8466 /* If we automatically created the clustered index, then
8467 MySQL does not know about it, and MySQL must NOT be aware
8468 of the index used on scan, to make it avoid checking if we
8469 update the column of the index. That is why we assert below
8470 that key_used_on_scan is the undefined value MAX_KEY.
8471 The column is the row id in the automatical generation case,
8472 and it will never be updated anyway. */
8473
8474
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 626460 times.
626460 if (key_used_on_scan != MAX_KEY) {
8475 log_errlog(WARNING_LEVEL, ER_INNODB_CLUSTERED_INDEX_PRIVATE, name,
8476 (ulong)key_used_on_scan);
8477 }
8478 }
8479
8480 /* Index block size in InnoDB: used by MySQL in query optimization */
8481 4025296 stats.block_size = UNIV_PAGE_SIZE;
8482
8483 /* Only if the table has an AUTOINC column. */
8484
4/4
✓ Branch 0 taken 4025295 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 4025246 times.
✓ Branch 3 taken 49 times.
4025296 if (m_prebuilt->table != nullptr && !m_prebuilt->table->ibd_file_missing &&
8485
2/2
✓ Branch 0 taken 1483897 times.
✓ Branch 1 taken 2541349 times.
4025246 table->found_next_number_field != NULL) {
8486 1483897 dict_table_t *ib_table = m_prebuilt->table;
8487
8488
1/2
✓ Branch 0 taken 1483898 times.
✗ Branch 1 not taken.
1483897 dict_table_autoinc_lock(ib_table);
8489
8490
1/2
✓ Branch 0 taken 1483898 times.
✗ Branch 1 not taken.
1483898 uint64_t autoinc = dict_table_autoinc_read(ib_table);
8491 1483898 uint64_t autoinc_persisted = 0;
8492
8493
1/2
✓ Branch 0 taken 1483898 times.
✗ Branch 1 not taken.
1483898 mutex_enter(ib_table->autoinc_persisted_mutex);
8494 1483898 autoinc_persisted = ib_table->autoinc_persisted;
8495
1/2
✓ Branch 0 taken 1483898 times.
✗ Branch 1 not taken.
1483898 mutex_exit(ib_table->autoinc_persisted_mutex);
8496
8497 /* Since a table can already be "open" in InnoDB's internal
8498 data dictionary, we only init the autoinc counter once, the
8499 first time the table is loaded. We can safely reuse the
8500 autoinc value from a previous MySQL open. */
8501
4/4
✓ Branch 0 taken 1459986 times.
✓ Branch 1 taken 23912 times.
✓ Branch 2 taken 85662 times.
✓ Branch 3 taken 1374324 times.
1483898 if (autoinc == 0 || autoinc == autoinc_persisted) {
8502 /* If autoinc is 0, it means the counter was never
8503 used or imported from a tablespace without .cfg file.
8504 We have to search the index to get proper counter.
8505 If only the second condition is true, it means it's
8506 the first time open for the table, we just want to
8507 calculate the next counter */
8508
1/2
✓ Branch 0 taken 109574 times.
✗ Branch 1 not taken.
109574 innobase_initialize_autoinc();
8509 }
8510
8511
1/2
✓ Branch 0 taken 1483898 times.
✗ Branch 1 not taken.
1483898 dict_table_autoinc_set_col_pos(
8512 1483898 ib_table, table->found_next_number_field->field_index());
8513
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1483898 times.
1483898 ut_ad(dict_table_has_autoinc_col(ib_table));
8514
8515
1/2
✓ Branch 0 taken 1483896 times.
✗ Branch 1 not taken.
1483898 dict_table_autoinc_unlock(ib_table);
8516 }
8517
8518 /* Set plugin parser for fulltext index */
8519
2/2
✓ Branch 0 taken 10099122 times.
✓ Branch 1 taken 4025296 times.
14124418 for (uint i = 0; i < table->s->keys; i++) {
8520
2/2
✓ Branch 0 taken 1254 times.
✓ Branch 1 taken 10097868 times.
10099122 if (table->key_info[i].flags & HA_USES_PARSER) {
8521
1/2
✓ Branch 0 taken 1254 times.
✗ Branch 1 not taken.
1254 dict_index_t *index = innobase_get_index(i);
8522 1254 plugin_ref parser = table->key_info[i].parser;
8523
8524
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1254 times.
1254 ut_ad(index->type & DICT_FTS);
8525 1254 index->parser =
8526 1254 static_cast<st_mysql_ftparser *>(plugin_decl(parser)->info);
8527
8528 1254 index->is_ngram = strncmp(plugin_name(parser)->str, FTS_NGRAM_PARSER_NAME,
8529 1254 plugin_name(parser)->length) == 0;
8530
8531
3/4
✓ Branch 0 taken 1255 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1251 times.
1254 DBUG_EXECUTE_IF("fts_instrument_use_default_parser",
8532 index->parser = &fts_default_parser;);
8533 }
8534 }
8535
8536
1/2
✓ Branch 0 taken 4025294 times.
✗ Branch 1 not taken.
4025296 info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
8537
8538 dberr_t err =
8539
1/2
✓ Branch 0 taken 4025277 times.
✗ Branch 1 not taken.
4025294 dict_set_compression(m_prebuilt->table, table->s->compress.str, false);
8540
8541
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3566383 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 458893 times.
4025277 switch (err) {
8542 1 case DB_NOT_FOUND:
8543 case DB_UNSUPPORTED:
8544 /* We will do another check before the create
8545 table and push the error to the client there. */
8546 1 break;
8547
8548 3566383 case DB_IO_NO_PUNCH_HOLE_TABLESPACE:
8549 /* We did the check in the 'if' above. */
8550
8551 case DB_IO_NO_PUNCH_HOLE_FS:
8552 /* During open we can't check whether the FS supports
8553 punch hole or not, at least on Linux. */
8554 3566383 break;
8555
8556 default:
8557 ut_error;
8558
8559 458893 case DB_SUCCESS:
8560 458893 break;
8561 }
8562
8563 #ifdef UNIV_DEBUG
8564 fts_aux_table_t aux_table;
8565
8566
2/4
✓ Branch 0 taken 4025281 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4025281 times.
4025277 if (fts_is_aux_table_name(&aux_table, norm_name, strlen(norm_name))) {
8567 ut_ad(m_prebuilt->table->is_fts_aux());
8568 }
8569 #endif /* UNIV_DEBUG */
8570
8571
2/4
✓ Branch 0 taken 4025290 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4025290 times.
4025281 if (m_prebuilt->table->is_fts_aux()) {
8572 dict_table_close(m_prebuilt->table, false, false);
8573 }
8574
8575 4025287 return 0;
8576 4025400 }
8577
8578 318820 handler *ha_innobase::clone(const char *name, /*!< in: table name */
8579 MEM_ROOT *mem_root) /*!< in: memory context */
8580 {
8581
1/2
✓ Branch 0 taken 318820 times.
✗ Branch 1 not taken.
318820 DBUG_TRACE;
8582
8583 ha_innobase *new_handler =
8584
3/4
✓ Branch 0 taken 318820 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 318819 times.
✓ Branch 3 taken 1 times.
318820 dynamic_cast<ha_innobase *>(handler::clone(name, mem_root));
8585
8586
2/2
✓ Branch 0 taken 318819 times.
✓ Branch 1 taken 1 times.
318820 if (new_handler != nullptr) {
8587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 318819 times.
318819 assert(new_handler->m_prebuilt != nullptr);
8588
8589 318819 new_handler->m_prebuilt->select_lock_type = m_prebuilt->select_lock_type;
8590 }
8591
8592 318820 return new_handler;
8593 318820 }
8594
8595 1856768 uint ha_innobase::max_supported_key_part_length(
8596 HA_CREATE_INFO *create_info) const {
8597 /* A table format specific index column length check will be performed
8598 at ha_innobase::add_index() and row_create_index_for_mysql() */
8599
2/2
✓ Branch 0 taken 6191 times.
✓ Branch 1 taken 1850577 times.
1856768 switch (create_info->row_type) {
8600 6191 case ROW_TYPE_REDUNDANT:
8601 case ROW_TYPE_COMPACT:
8602 6191 return (REC_ANTELOPE_MAX_INDEX_COL_LEN - 1);
8603 break;
8604 1850577 default:
8605 1850577 return (REC_VERSION_56_MAX_INDEX_COL_LEN);
8606 }
8607 }
8608
8609 /** Closes a handle to an InnoDB table.
8610 @return 0 */
8611
8612 3916977 int ha_innobase::close() {
8613
1/2
✓ Branch 0 taken 3916982 times.
✗ Branch 1 not taken.
3916977 DBUG_TRACE;
8614
8615
2/2
✓ Branch 0 taken 336 times.
✓ Branch 1 taken 3916646 times.
3916982 if (m_prebuilt->m_temp_read_shared) {
8616 336 temp_prebuilt_vec *vec = m_prebuilt->table->temp_prebuilt;
8617
2/4
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 336 times.
336 ut_ad(m_prebuilt->table->is_intrinsic());
8618
2/4
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 336 times.
✗ Branch 3 not taken.
336 vec->erase(std::remove(vec->begin(), vec->end(), m_prebuilt), vec->end());
8619 }
8620
8621
1/2
✓ Branch 0 taken 3916982 times.
✗ Branch 1 not taken.
3916982 free_share_and_nullify(&m_share);
8622
8623
1/2
✓ Branch 0 taken 3916982 times.
✗ Branch 1 not taken.
3916982 row_prebuilt_free(m_prebuilt, false);
8624
8625
2/2
✓ Branch 0 taken 197506 times.
✓ Branch 1 taken 3719476 times.
3916982 if (m_upd_buf != nullptr) {
8626
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 197506 times.
197506 ut_ad(m_upd_buf_size != 0);
8627
1/2
✓ Branch 0 taken 197506 times.
✗ Branch 1 not taken.
197506 my_free(m_upd_buf);
8628 197506 m_upd_buf = nullptr;
8629 197506 m_upd_buf_size = 0;
8630 }
8631
8632 3916982 MONITOR_INC(MONITOR_TABLE_CLOSE);
8633
8634 /* Tell InnoDB server that there might be work for
8635 utility threads: */
8636
8637
1/2
✓ Branch 0 taken 3916982 times.
✗ Branch 1 not taken.
3916982 srv_active_wake_master_thread();
8638
8639 3916982 return 0;
8640 3916982 }
8641
8642 /* The following accessor functions should really be inside MySQL code! */
8643
8644 /** Gets field offset for a field in a table.
8645 @param[in] table MySQL table object
8646 @param[in] field MySQL field object
8647 @return offset */
8648 2302554716 static inline uint get_field_offset(const TABLE *table, const Field *field) {
8649 2302554716 return field->offset(table->record[0]);
8650 }
8651
8652 #ifdef WITH_WSREP
8653 3565 int wsrep_innobase_mysql_sort(int mysql_type, uint charset_number,
8654 unsigned char *str, unsigned int str_length,
8655 unsigned int buf_length) {
8656 CHARSET_INFO *charset;
8657 enum_field_types mysql_tp;
8658 3565 int ret_length = str_length;
8659
8660
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3565 times.
3565 assert(str_length != UNIV_SQL_NULL);
8661
8662 3565 mysql_tp = (enum_field_types)mysql_type;
8663
8664
1/3
✓ Branch 0 taken 3565 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
3565 switch (mysql_tp) {
8665 3565 case MYSQL_TYPE_BIT:
8666 case MYSQL_TYPE_STRING:
8667 case MYSQL_TYPE_VAR_STRING:
8668 case MYSQL_TYPE_TINY_BLOB:
8669 case MYSQL_TYPE_MEDIUM_BLOB:
8670 case MYSQL_TYPE_BLOB:
8671 case MYSQL_TYPE_LONG_BLOB:
8672 case MYSQL_TYPE_VARCHAR: {
8673 3565 uchar tmp_str[REC_VERSION_56_MAX_INDEX_COL_LEN] = {'\0'};
8674 3565 uint tmp_length = REC_VERSION_56_MAX_INDEX_COL_LEN;
8675
8676 /* Use the charset number to pick the right charset struct for
8677 the comparison. Since the MySQL function get_charset may be
8678 slow before Bar removes the mutex operation there, we first
8679 look at 2 common charsets directly. */
8680
8681
2/2
✓ Branch 0 taken 3529 times.
✓ Branch 1 taken 36 times.
3565 if (charset_number == default_charset_info->number) {
8682 3529 charset = default_charset_info;
8683
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 12 times.
36 } else if (charset_number == my_charset_latin1.number) {
8684 24 charset = &my_charset_latin1;
8685 } else {
8686
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 charset = get_charset(charset_number, MYF(MY_WME));
8687
8688
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (charset == NULL) {
8689 sql_print_error(
8690 "InnoDB needs charset %lu for doing "
8691 "a comparison, but MySQL cannot "
8692 "find that charset.",
8693 (ulong)charset_number);
8694 ut_a(0);
8695 }
8696 }
8697
8698
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3565 times.
3565 ut_a(str_length <= tmp_length);
8699 3565 memcpy(tmp_str, str, str_length);
8700
8701
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3565 times.
3565 if (wsrep_protocol_version < 3) {
8702 tmp_length = charset->coll->strnxfrm(
8703 charset, str, str_length, str_length, tmp_str, tmp_length, 0);
8704 assert(tmp_length <= str_length);
8705 } else {
8706 /* strnxfrm will expand the destination string,
8707 protocols < 3 truncated the sorted sring
8708 protocols >= 3 gets full sorted sring */
8709
1/2
✓ Branch 0 taken 3565 times.
✗ Branch 1 not taken.
3565 tmp_length = charset->coll->strnxfrm(
8710 charset, str, buf_length, str_length, tmp_str, str_length, 0);
8711
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3565 times.
3565 assert(tmp_length <= buf_length);
8712 3565 ret_length = tmp_length;
8713 }
8714 3565 break;
8715 }
8716 case MYSQL_TYPE_DECIMAL:
8717 case MYSQL_TYPE_TINY:
8718 case MYSQL_TYPE_SHORT:
8719 case MYSQL_TYPE_LONG:
8720 case MYSQL_TYPE_FLOAT:
8721 case MYSQL_TYPE_DOUBLE:
8722 case MYSQL_TYPE_NULL:
8723 case MYSQL_TYPE_TIMESTAMP:
8724 case MYSQL_TYPE_LONGLONG:
8725 case MYSQL_TYPE_INT24:
8726 case MYSQL_TYPE_DATE:
8727 case MYSQL_TYPE_TIME:
8728 case MYSQL_TYPE_DATETIME:
8729 case MYSQL_TYPE_YEAR:
8730 case MYSQL_TYPE_NEWDATE:
8731 case MYSQL_TYPE_NEWDECIMAL:
8732 case MYSQL_TYPE_ENUM:
8733 case MYSQL_TYPE_SET:
8734 case MYSQL_TYPE_GEOMETRY:
8735 break;
8736 default:
8737 break;
8738 }
8739
8740 3565 return ret_length;
8741 }
8742
8743 /** Stores a key value for a row to a buffer.
8744 @return key value length as stored in buff */
8745 2796376 uint wsrep_store_key_val_for_row(THD *thd, TABLE *table, uint keynr, char *buff,
8746 uint buff_len, const uchar *record,
8747 bool *key_is_null, row_prebuilt_t *prebuilt) {
8748 2796376 KEY *key_info = table->key_info + keynr;
8749 2796376 KEY_PART_INFO *key_part = key_info->key_part;
8750 2796376 KEY_PART_INFO *end = key_part + key_info->user_defined_key_parts;
8751 2796376 char *buff_start = buff;
8752 enum_field_types mysql_type;
8753 Field *field;
8754 2796376 uint buff_space = buff_len;
8755
8756
1/2
✓ Branch 0 taken 2796376 times.
✗ Branch 1 not taken.
2796376 DBUG_ENTER("wsrep_store_key_val_for_row");
8757
8758 2796376 memset(buff, 0, buff_len);
8759 2796376 *key_is_null = true;
8760
8761
2/2
✓ Branch 0 taken 2796422 times.
✓ Branch 1 taken 2796376 times.
5592798 for (; key_part != end; key_part++) {
8762 2796422 uchar sorted[REC_VERSION_56_MAX_INDEX_COL_LEN] = {'\0'};
8763 2796422 bool part_is_null = false;
8764
8765
2/2
✓ Branch 0 taken 3143 times.
✓ Branch 1 taken 2793279 times.
2796422 if (key_part->null_bit) {
8766
1/2
✓ Branch 0 taken 3143 times.
✗ Branch 1 not taken.
3143 if (buff_space > 0) {
8767
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3140 times.
3143 if (record[key_part->null_offset] & key_part->null_bit) {
8768 3 *buff = 1;
8769 3 part_is_null = true;
8770 } else {
8771 3140 *buff = 0;
8772 }
8773
8774 3143 buff++;
8775 3143 buff_space--;
8776 } else {
8777 fprintf(stderr, "WSREP: key truncated: %s\n", wsrep_thd_query(thd));
8778 }
8779 }
8780
8781
2/2
✓ Branch 0 taken 2796419 times.
✓ Branch 1 taken 3 times.
2796422 if (!part_is_null) *key_is_null = false;
8782
8783 2796422 field = key_part->field;
8784
1/2
✓ Branch 0 taken 2796422 times.
✗ Branch 1 not taken.
2796422 mysql_type = field->type();
8785
8786
2/2
✓ Branch 0 taken 3559 times.
✓ Branch 1 taken 2792863 times.
2796422 if (mysql_type == MYSQL_TYPE_VARCHAR) {
8787 /* >= 5.0.3 true VARCHAR */
8788 ulint lenlen;
8789 ulint len;
8790 const byte *data;
8791 ulint key_len;
8792 ulint true_len;
8793 const CHARSET_INFO *cs;
8794 3559 int error = 0;
8795
8796 3559 key_len = key_part->length;
8797
8798
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3559 times.
3559 if (part_is_null) {
8799 true_len = key_len + 2;
8800 if (true_len > buff_space) {
8801 fprintf(stderr, "WSREP: key truncated: %s\n", wsrep_thd_query(thd));
8802 true_len = buff_space;
8803 }
8804 buff += true_len;
8805 buff_space -= true_len;
8806 continue;
8807 }
8808
1/2
✓ Branch 0 taken 3559 times.
✗ Branch 1 not taken.
3559 cs = field->charset();
8809
8810
1/2
✓ Branch 0 taken 3559 times.
✗ Branch 1 not taken.
3559 lenlen = (ulint)(((Field_varstring *)field)->get_length_bytes());
8811
8812 7118 data = row_mysql_read_true_varchar(
8813
1/2
✓ Branch 0 taken 3559 times.
✗ Branch 1 not taken.
3559 &len, (byte *)(record + (ulint)get_field_offset(table, field)),
8814 lenlen);
8815
8816 3559 true_len = len;
8817
8818 /* For multi byte character sets we need to calculate
8819 the true length of the key */
8820
8821
3/4
✓ Branch 0 taken 3559 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3534 times.
✓ Branch 3 taken 25 times.
3559 if (len > 0 && cs->mbmaxlen > 1) {
8822 3534 true_len = (ulint)cs->cset->well_formed_len(
8823 3534 cs, (const char *)data, (const char *)data + len,
8824
1/2
✓ Branch 0 taken 3534 times.
✗ Branch 1 not taken.
3534 (uint)(key_len / cs->mbmaxlen), &error);
8825 }
8826
8827 /* In a column prefix index, we may need to truncate
8828 the stored value: */
8829
8830
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3559 times.
3559 if (true_len > key_len) {
8831 true_len = key_len;
8832 }
8833
8834 3559 memcpy(sorted, data, true_len);
8835 3559 true_len =
8836
1/2
✓ Branch 0 taken 3559 times.
✗ Branch 1 not taken.
3559 wsrep_innobase_mysql_sort(mysql_type, cs->number, sorted, true_len,
8837 REC_VERSION_56_MAX_INDEX_COL_LEN);
8838
8839
1/2
✓ Branch 0 taken 3559 times.
✗ Branch 1 not taken.
3559 if (wsrep_protocol_version > 1) {
8840 /* Note that we always reserve the maximum possible
8841 length of the true VARCHAR in the key value, though
8842 only len first bytes after the 2 length bytes contain
8843 actual data. The rest of the space was reset to zero
8844 in the bzero() call above. */
8845
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3559 times.
3559 if (true_len > buff_space) {
8846 fprintf(stderr, "WSREP: key truncated: %s\n", wsrep_thd_query(thd));
8847 true_len = buff_space;
8848 }
8849 3559 memcpy(buff, sorted, true_len);
8850 3559 buff += true_len;
8851 3559 buff_space -= true_len;
8852 } else {
8853 buff += key_len;
8854 }
8855
2/4
✓ Branch 0 taken 2792863 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2792863 times.
✗ Branch 3 not taken.
2792863 } else if (mysql_type == MYSQL_TYPE_TINY_BLOB ||
8856
1/2
✓ Branch 0 taken 2792863 times.
✗ Branch 1 not taken.
2792863 mysql_type == MYSQL_TYPE_MEDIUM_BLOB ||
8857
1/2
✓ Branch 0 taken 2792863 times.
✗ Branch 1 not taken.
2792863 mysql_type == MYSQL_TYPE_BLOB ||
8858
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2792863 times.
2792863 mysql_type == MYSQL_TYPE_LONG_BLOB ||
8859 /* MYSQL_TYPE_GEOMETRY data is treated
8860 as BLOB data in innodb. */
8861 mysql_type == MYSQL_TYPE_GEOMETRY) {
8862 const CHARSET_INFO *cs;
8863 ulint key_len;
8864 ulint true_len;
8865 int error = 0;
8866 ulint blob_len;
8867 const byte *blob_data;
8868
8869 ut_a(key_part->key_part_flag & HA_PART_KEY_SEG);
8870
8871 key_len = key_part->length;
8872
8873 if (part_is_null) {
8874 true_len = key_len + 2;
8875 if (true_len > buff_space) {
8876 fprintf(stderr, "WSREP: key truncated: %s\n", wsrep_thd_query(thd));
8877 true_len = buff_space;
8878 }
8879 buff += true_len;
8880 buff_space -= true_len;
8881
8882 continue;
8883 }
8884
8885 cs = field->charset();
8886
8887 blob_data = row_mysql_read_blob_ref(
8888 &blob_len, (byte *)(record + (ulint)get_field_offset(table, field)),
8889 (ulint)field->pack_length(), false, 0, 0, &prebuilt->compress_heap);
8890
8891 true_len = blob_len;
8892
8893 ut_a(get_field_offset(table, field) == key_part->offset);
8894
8895 /* For multi byte character sets we need to calculate
8896 the true length of the key */
8897
8898 if (blob_len > 0 && cs->mbmaxlen > 1) {
8899 true_len = (ulint)cs->cset->well_formed_len(
8900 cs, (const char *)blob_data, (const char *)blob_data + blob_len,
8901 (uint)(key_len / cs->mbmaxlen), &error);
8902 }
8903
8904 /* All indexes on BLOB and TEXT are column prefix
8905 indexes, and we may need to truncate the data to be
8906 stored in the key value: */
8907
8908 if (true_len > key_len) {
8909 true_len = key_len;
8910 }
8911
8912 memcpy(sorted, blob_data, true_len);
8913 true_len =
8914 wsrep_innobase_mysql_sort(mysql_type, cs->number, sorted, true_len,
8915 REC_VERSION_56_MAX_INDEX_COL_LEN);
8916
8917 /* Note that we always reserve the maximum possible
8918 length of the BLOB prefix in the key value. */
8919 ut_a(wsrep_protocol_version > 1);
8920 if (true_len > buff_space) {
8921 ib::warn() << "WSREP: key truncated: %s " << wsrep_thd_query(thd);
8922 true_len = buff_space;
8923 }
8924 memcpy(buff, sorted, true_len);
8925 buff += true_len;
8926 buff_space -= true_len;
8927
8928 } else {
8929 /* Here we handle all other data types except the
8930 true VARCHAR, BLOB and TEXT. Note that the column
8931 value we store may be also in a column prefix index. */
8932
8933 2792863 const CHARSET_INFO *cs = NULL;
8934 ulint true_len;
8935 ulint key_len;
8936 const uchar *src_start;
8937 2792863 int error = 0;
8938 enum_field_types real_type;
8939
8940 2792863 key_len = key_part->length;
8941
8942
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2792860 times.
2792863 if (part_is_null) {
8943 3 true_len = key_len;
8944
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (true_len > buff_space) {
8945 fprintf(stderr, "WSREP: key truncated: %s\n", wsrep_thd_query(thd));
8946 true_len = buff_space;
8947 }
8948 3 buff += true_len;
8949 3 buff_space -= true_len;
8950
8951 3 continue;
8952 }
8953
8954 2792860 src_start = record + key_part->offset;
8955
1/2
✓ Branch 0 taken 2792860 times.
✗ Branch 1 not taken.
2792860 real_type = field->real_type();
8956 2792860 true_len = key_len;
8957
8958 /* Character set for the field is defined only
8959 to fields whose type is string and real field
8960 type is not enum or set. For these fields check
8961 if character set is multi byte. */
8962
8963
4/6
✓ Branch 0 taken 2792847 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 2792847 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2792847 times.
✗ Branch 5 not taken.
2792860 if (real_type != MYSQL_TYPE_ENUM && real_type != MYSQL_TYPE_SET &&
8964
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2792843 times.
2792847 (mysql_type == MYSQL_TYPE_VAR_STRING ||
8965 mysql_type == MYSQL_TYPE_STRING)) {
8966
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 cs = field->charset();
8967
8968 /* For multi byte character sets we need to
8969 calculate the true length of the key */
8970
8971
3/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
4 if (key_len > 0 && cs->mbmaxlen > 1) {
8972 2 true_len = (ulint)cs->cset->well_formed_len(
8973 cs, (const char *)src_start, (const char *)src_start + key_len,
8974
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 (uint)(key_len / cs->mbmaxlen), &error);
8975 }
8976 4 memcpy(sorted, src_start, true_len);
8977 4 true_len =
8978
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 wsrep_innobase_mysql_sort(mysql_type, cs->number, sorted, true_len,
8979 REC_VERSION_56_MAX_INDEX_COL_LEN);
8980
8981
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (true_len > buff_space) {
8982 fprintf(stderr, "WSREP: key truncated: %s\n", wsrep_thd_query(thd));
8983 true_len = buff_space;
8984 }
8985 4 memcpy(buff, sorted, true_len);
8986 } else {
8987 2792856 memcpy(buff, src_start, true_len);
8988 }
8989 2792860 buff += true_len;
8990 2792860 buff_space -= true_len;
8991 }
8992 }
8993
8994
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2796376 times.
2796376 ut_a(buff <= buff_start + buff_len);
8995
8996
1/2
✓ Branch 0 taken 2796376 times.
✗ Branch 1 not taken.
2796376 DBUG_RETURN((uint)(buff - buff_start));
8997 }
8998 #endif /* WITH_WSREP */
8999
9000 /** Compare two character string according to their charset.
9001 @param[in] cs Character set
9002 @param[in] p1 Key
9003 @param[in] p2 Node */
9004 270294085 extern int innobase_fts_text_cmp(const void *cs, const void *p1,
9005 const void *p2) {
9006 270294085 const CHARSET_INFO *charset = (const CHARSET_INFO *)cs;
9007 270294085 const fts_string_t *s1 = (const fts_string_t *)p1;
9008 270294085 const fts_string_t *s2 = (const fts_string_t *)p2;
9009
9010 540578288 return (ha_compare_text(charset, s1->f_str, static_cast<uint>(s1->f_len),
9011 270294085 s2->f_str, static_cast<uint>(s2->f_len), false));
9012 }
9013
9014 /** Compare two FTS character strings case insensitively according to their
9015 charset. This assumes that s1 is already in lower case.
9016 @param[in] cs character set
9017 @param[in] s1 key
9018 @param[in] s2 node
9019 @return 0 if the two strings are equal */
9020 1072 int innobase_fts_nocase_compare(const CHARSET_INFO *cs, const fts_string_t *s1,
9021 const fts_string_t *s2) {
9022 ulint newlen;
9023
9024
2/2
✓ Branch 0 taken 1029 times.
✓ Branch 1 taken 43 times.
1072 if (!my_binary_compare(cs)) {
9025 1029 my_casedn_str(cs, (char *)s2->f_str);
9026 }
9027
9028 1072 newlen = strlen((const char *)s2->f_str);
9029
9030 2144 return (ha_compare_text(cs, s1->f_str, static_cast<uint>(s1->f_len),
9031 1072 s2->f_str, static_cast<uint>(newlen), false));
9032 }
9033
9034 #endif /* UNIV_HOTBACKUP */
9035
9036 /** Compare two character strings case insensitively according to their
9037 charset.
9038 @param[in] cs character set
9039 @param[in] s1 string 1
9040 @param[in] s2 string 2
9041 @return 0 if the two strings are equal */
9042 int innobase_nocase_compare(const void *cs, const char *s1, const char *s2) {
9043 const CHARSET_INFO *charset = static_cast<const CHARSET_INFO *>(cs);
9044 const uchar *str1 = reinterpret_cast<const uchar *>(s1);
9045 const uchar *str2 = reinterpret_cast<const uchar *>(s2);
9046 uint len1 = static_cast<uint>(strlen(s1));
9047 uint len2 = static_cast<uint>(strlen(s2));
9048
9049 /* This function returns zero if the two strings are equal. */
9050 return (ha_compare_text(charset, str1, len1, str2, len2, false));
9051 }
9052
9053 #ifndef UNIV_HOTBACKUP
9054
9055 2492017 ulint innobase_strnxfrm(const CHARSET_INFO *cs, const uchar *str,
9056 const ulint len) {
9057 uchar mystr[2];
9058 ulint value;
9059
9060
3/4
✓ Branch 0 taken 2492051 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2492049 times.
2492017 if (!str || len == 0) {
9061 return (0);
9062 }
9063
9064
1/2
✓ Branch 0 taken 2491819 times.
✗ Branch 1 not taken.
2492049 my_strnxfrm(cs, (uchar *)mystr, 2, str, len);
9065
9066 2491819 value = mach_read_from_2(mystr);
9067
9068
2/2
✓ Branch 0 taken 2483704 times.
✓ Branch 1 taken 8072 times.
2491776 if (value > 255) {
9069 2483704 value = value / 256;
9070 }
9071
9072 2491776 return (value);
9073 }
9074
9075 /** Compare two character string according to their charset.
9076 @param[in] cs Character set
9077 @param[in] p1 Key
9078 @param[in] p2 Node */
9079 549 extern int innobase_fts_text_cmp_prefix(const void *cs, const void *p1,
9080 const void *p2) {
9081 549 const CHARSET_INFO *charset = (const CHARSET_INFO *)cs;
9082 549 const fts_string_t *s1 = (const fts_string_t *)p1;
9083 549 const fts_string_t *s2 = (const fts_string_t *)p2;
9084 int result;
9085
9086 1098 result = ha_compare_text(charset, s2->f_str, static_cast<uint>(s2->f_len),
9087 549 s1->f_str, static_cast<uint>(s1->f_len), true);
9088
9089 /* We switched s1, s2 position in ha_compare_text. So we need
9090 to negate the result */
9091 549 return (-result);
9092 }
9093
9094 /** Makes all characters in a string lower case.
9095 @param[in] cs Character set
9096 @param[in] src String to put in lower case
9097 @param[in] src_len Input string length
9098 @param[in] dst Buffer for result string
9099 @param[in] dst_len Buffer size */
9100 1478154 extern size_t innobase_fts_casedn_str(CHARSET_INFO *cs, char *src,
9101 size_t src_len, char *dst,
9102 size_t dst_len) {
9103
2/2
✓ Branch 0 taken 1476672 times.
✓ Branch 1 taken 1482 times.
1478154 if (cs->casedn_multiply == 1) {
9104 1476672 memcpy(dst, src, src_len);
9105 1476672 dst[src_len] = 0;
9106 1476672 my_casedn_str(cs, dst);
9107
9108 1476858 return (strlen(dst));
9109 } else {
9110 1482 return (cs->cset->casedn(cs, src, src_len, dst, dst_len));
9111 }
9112 }
9113
9114 /** Get the next token from the given string and store it in *token.
9115 It is mostly copied from MyISAM's doc parsing function ft_simple_get_word()
9116 @return length of string processed */
9117 1566848 ulint innobase_mysql_fts_get_token(
9118 CHARSET_INFO *cs, /*!< in: Character set */
9119 const byte *start, /*!< in: start of text */
9120 const byte *end, /*!< in: one character past end of
9121 text */
9122 bool extra_word_chars, /*!< in: whether consider all non-whitespace
9123 characters to be word characters */
9124 fts_string_t *token) /*!< out: token's text */
9125 {
9126 int mbl;
9127 1566848 const uchar *doc = start;
9128
9129
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1566760 times.
1566848 ut_a(cs);
9130
9131 1566760 token->f_n_char = token->f_len = 0;
9132 1566760 token->f_str = nullptr;
9133
9134 for (;;) {
9135
2/2
✓ Branch 0 taken 10173 times.
✓ Branch 1 taken 7510488 times.
7520661 if (doc >= end) {
9136 10173 return (doc - start);
9137 }
9138
9139 int ctype;
9140
9141
1/2
✓ Branch 0 taken 7511653 times.
✗ Branch 1 not taken.
7510488 mbl = cs->cset->ctype(cs, &ctype, doc, (const uchar *)end);
9142
9143
2/2
✓ Branch 0 taken 1557737 times.
✓ Branch 1 taken 5953901 times.
7511653 if (true_word_char(ctype, extra_word_chars, *doc)) {
9144 1557737 break;
9145 }
9146
9147
2/4
✓ Branch 0 taken 5955352 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
5953901 doc += mbl > 0 ? mbl : (mbl < 0 ? -mbl : 1);
9148 5953901 }
9149
9150 1557737 ulint length = 0;
9151
9152 1557737 token->f_str = const_cast<byte *>(doc);
9153
9154
2/2
✓ Branch 0 taken 26553072 times.
✓ Branch 1 taken 663756 times.
27216828 while (doc < end) {
9155 int ctype;
9156
9157
1/2
✓ Branch 0 taken 26552418 times.
✗ Branch 1 not taken.
26553072 mbl = cs->cset->ctype(cs, &ctype, (uchar *)doc, (uchar *)end);
9158
2/2
✓ Branch 0 taken 894479 times.
✓ Branch 1 taken 25659091 times.
26552418 if (!true_word_char(ctype, extra_word_chars, *doc)) {
9159 894479 break;
9160 }
9161
9162 25659091 ++length;
9163
9164
1/4
✓ Branch 0 taken 25662145 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
25659091 doc += mbl > 0 ? mbl : (mbl < 0 ? -mbl : 1);
9165 }
9166
9167 1558235 token->f_len = (uint)(doc - token->f_str);
9168 1558235 token->f_n_char = length;
9169
9170 1558235 return (doc - start);
9171 }
9172
9173 /** Converts a MySQL type to an InnoDB type. Note that this function returns
9174 the 'mtype' of InnoDB. InnoDB differentiates between MySQL's old <= 4.1
9175 VARCHAR and the new true VARCHAR in >= 5.0.3 by the 'prtype'.
9176 @param[out] unsigned_flag DATA_UNSIGNED if an 'unsigned type'; at least
9177 ENUM and SET, and unsigned integer types are 'unsigned types'
9178 @param[in] f MySQL Field
9179 @return DATA_BINARY, DATA_VARCHAR, ... */
9180 21488816 ulint get_innobase_type_from_mysql_type(ulint *unsigned_flag, const void *f) {
9181 21488816 const class Field *field = reinterpret_cast<const class Field *>(f);
9182
9183 /* The following asserts try to check that the MySQL type code fits in
9184 8 bits: this is used in ibuf and also when DATA_NOT_NULL is ORed to
9185 the type */
9186
9187 assert((ulint)MYSQL_TYPE_STRING < 256);
9188 assert((ulint)MYSQL_TYPE_VAR_STRING < 256);
9189 assert((ulint)MYSQL_TYPE_DOUBLE < 256);
9190 assert((ulint)MYSQL_TYPE_FLOAT < 256);
9191 assert((ulint)MYSQL_TYPE_DECIMAL < 256);
9192
9193
2/2
✓ Branch 0 taken 6962320 times.
✓ Branch 1 taken 14526499 times.
21488816 if (field->is_flag_set(UNSIGNED_FLAG)) {
9194 6962320 *unsigned_flag = DATA_UNSIGNED;
9195 } else {
9196 14526499 *unsigned_flag = 0;
9197 }
9198
9199
4/4
✓ Branch 0 taken 19971480 times.
✓ Branch 1 taken 1517339 times.
✓ Branch 2 taken 1604934 times.
✓ Branch 3 taken 19883884 times.
41460298 if (field->real_type() == MYSQL_TYPE_ENUM ||
9200
2/2
✓ Branch 0 taken 87595 times.
✓ Branch 1 taken 19883884 times.
19971480 field->real_type() == MYSQL_TYPE_SET) {
9201 /* MySQL has field->type() a string type for these, but the
9202 data is actually internally stored as an unsigned integer
9203 code! */
9204
9205 1604934 *unsigned_flag = DATA_UNSIGNED; /* MySQL has its own unsigned
9206 flag set to zero, even though
9207 internally this is an unsigned
9208 integer type */
9209 1604934 return (DATA_INT);
9210 }
9211
9212
9/12
✓ Branch 0 taken 6088453 times.
✓ Branch 1 taken 1943406 times.
✓ Branch 2 taken 20810 times.
✓ Branch 3 taken 9665340 times.
✓ Branch 4 taken 495708 times.
✓ Branch 5 taken 61879 times.
✓ Branch 6 taken 29321 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3926 times.
✓ Branch 9 taken 1575042 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
19883884 switch (field->type()) {
9213 /* NOTE that we only allow string types in DATA_MYSQL and
9214 DATA_VARMYSQL */
9215 6088453 case MYSQL_TYPE_VAR_STRING: /* old <= 4.1 VARCHAR */
9216 case MYSQL_TYPE_VARCHAR: /* new >= 5.0.3 true VARCHAR */
9217
2/2
✓ Branch 0 taken 41170 times.
✓ Branch 1 taken 6047283 times.
6088453 if (field->binary()) {
9218 41170 return (DATA_BINARY);
9219
2/2
✓ Branch 0 taken 71109 times.
✓ Branch 1 taken 5976174 times.
6047283 } else if (field->charset() == &my_charset_latin1) {
9220 71109 return (DATA_VARCHAR);
9221 } else {
9222 5976174 return (DATA_VARMYSQL);
9223 }
9224 1943406 case MYSQL_TYPE_BIT:
9225 case MYSQL_TYPE_STRING:
9226
2/2
✓ Branch 0 taken 15662 times.
✓ Branch 1 taken 1927744 times.
1943406 if (field->binary()) {
9227 15662 return (DATA_FIXBINARY);
9228
2/2
✓ Branch 0 taken 11123 times.
✓ Branch 1 taken 1916621 times.
1927744 } else if (field->charset() == &my_charset_latin1) {
9229 11123 return (DATA_CHAR);
9230 } else {
9231 1916621 return (DATA_MYSQL);
9232 }
9233 20810 case MYSQL_TYPE_NEWDECIMAL:
9234 20810 return (DATA_FIXBINARY);
9235 9665340 case MYSQL_TYPE_LONG:
9236 case MYSQL_TYPE_LONGLONG:
9237 case MYSQL_TYPE_TINY:
9238 case MYSQL_TYPE_SHORT:
9239 case MYSQL_TYPE_INT24:
9240 case MYSQL_TYPE_DATE:
9241 case MYSQL_TYPE_YEAR:
9242 case MYSQL_TYPE_NEWDATE:
9243 case MYSQL_TYPE_BOOL:
9244 9665340 return (DATA_INT);
9245 495708 case MYSQL_TYPE_TIME:
9246 case MYSQL_TYPE_DATETIME:
9247 case MYSQL_TYPE_TIMESTAMP:
9248 case MYSQL_TYPE_TIME2:
9249 case MYSQL_TYPE_DATETIME2:
9250 case MYSQL_TYPE_TIMESTAMP2:
9251
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 495708 times.
495708 switch (field->real_type()) {
9252 case MYSQL_TYPE_TIME:
9253 case MYSQL_TYPE_DATETIME:
9254 case MYSQL_TYPE_TIMESTAMP:
9255 return (DATA_INT);
9256 495708 default:
9257 assert((ulint)MYSQL_TYPE_DECIMAL < 256);
9258 [[fallthrough]];
9259 case MYSQL_TYPE_TIME2:
9260 case MYSQL_TYPE_DATETIME2:
9261 case MYSQL_TYPE_TIMESTAMP2:
9262 495708 return (DATA_FIXBINARY);
9263 }
9264 61879 case MYSQL_TYPE_FLOAT:
9265 61879 return (DATA_FLOAT);
9266 29321 case MYSQL_TYPE_DOUBLE:
9267 29321 return (DATA_DOUBLE);
9268 case MYSQL_TYPE_DECIMAL:
9269 return (DATA_DECIMAL);
9270 3926 case MYSQL_TYPE_GEOMETRY:
9271 3926 return (DATA_GEOMETRY);
9272 1575042 case MYSQL_TYPE_TINY_BLOB:
9273 case MYSQL_TYPE_MEDIUM_BLOB:
9274 case MYSQL_TYPE_BLOB:
9275 case MYSQL_TYPE_LONG_BLOB:
9276 case MYSQL_TYPE_JSON: // JSON fields are stored as BLOBs
9277 1575042 return (DATA_BLOB);
9278 case MYSQL_TYPE_NULL:
9279 /* MySQL currently accepts "NULL" datatype, but will
9280 reject such datatype in the next release. We will cope
9281 with it and not trigger assertion failure in 5.1 */
9282 break;
9283 default:
9284 ut_error;
9285 }
9286
9287 return (0);
9288 }
9289
9290 /** Converts a MySQL data-dictionary type to an InnoDB type. Also returns
9291 a few attributes which are useful for precise type calculation.
9292
9293 @note This function is version of get_innobase_type_from_mysql_type() with
9294 added knowledge about how additional attributes calculated (e.g. in
9295 create_table_info_t::create_table_def()) and about behavior of Field
9296 class and its descendats.
9297
9298 @note It allows to get InnoDB generic and precise types directly from MySQL
9299 data-dictionary info, bypassing expensive construction of Field objects.
9300
9301 @param[out] unsigned_flag DATA_UNSIGNED if an 'unsigned type'.
9302 @param[out] binary_type DATA_BINARY_TYPE if a 'binary type'.
9303 @param[out] charset_no Collation id for string types.
9304 @param[in] dd_type MySQL data-dictionary type.
9305 @param[in] field_charset Charset.
9306 @param[in] is_unsigned MySQL data-dictionary unsigned flag.
9307
9308 @return DATA_BINARY, DATA_VARCHAR, ... */
9309 557911 ulint get_innobase_type_from_mysql_dd_type(ulint *unsigned_flag,
9310 ulint *binary_type,
9311 ulint *charset_no,
9312 dd::enum_column_types dd_type,
9313 const CHARSET_INFO *field_charset,
9314 bool is_unsigned) {
9315 /* InnoDB's unsigned flag is based on UNSIGNED_FLAG bit in Field::flags.
9316 This bit is unset for Field objects by default. */
9317 557911 *unsigned_flag = 0;
9318 /* InnoDB's binary type flag is based on result of Field::binary() call.
9319 The latter returns true by default. */
9320 557911 *binary_type = DATA_BINARY_TYPE;
9321 /* InnoDB takes into account charset numbers only for columns which it
9322 considers of string type. */
9323 557911 *charset_no = 0;
9324
9325
9/13
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 175 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 766 times.
✓ Branch 4 taken 556877 times.
✓ Branch 5 taken 14 times.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
557911 switch (dd_type) {
9326 38 case dd::enum_column_types::ENUM:
9327 case dd::enum_column_types::SET:
9328 /* SQL-layer has its own unsigned flag set to zero, even though
9329 internally this is an unsigned integer type. */
9330 38 *unsigned_flag = DATA_UNSIGNED;
9331 /* ENUM and SET are handled as string types by SQL-layer,
9332 hence the charset check. */
9333
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 2 times.
38 if (field_charset != &my_charset_bin) *binary_type = 0;
9334 38 return (DATA_INT);
9335 175 case dd::enum_column_types::VAR_STRING: /* old <= 4.1 VARCHAR. */
9336 case dd::enum_column_types::VARCHAR: /* new >= 5.0.3 true VARCHAR. */
9337 175 *charset_no = field_charset->number;
9338
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 162 times.
175 if (field_charset == &my_charset_bin) {
9339 13 return (DATA_BINARY);
9340 } else {
9341 162 *binary_type = 0;
9342
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 122 times.
162 if (field_charset == &my_charset_latin1) {
9343 40 return (DATA_VARCHAR);
9344 } else {
9345 122 return (DATA_VARMYSQL);
9346 }
9347 }
9348 15 case dd::enum_column_types::BIT:
9349 /* MySQL always sets unsigned flag for both its BIT types. */
9350 15 *unsigned_flag = DATA_UNSIGNED;
9351 15 *charset_no = my_charset_bin.number;
9352 15 return (DATA_FIXBINARY);
9353 766 case dd::enum_column_types::STRING:
9354 766 *charset_no = field_charset->number;
9355
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 713 times.
766 if (field_charset == &my_charset_bin) {
9356 53 return (DATA_FIXBINARY);
9357 } else {
9358 713 *binary_type = 0;
9359
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 701 times.
713 if (field_charset == &my_charset_latin1) {
9360 12 return (DATA_CHAR);
9361 } else {
9362 701 return (DATA_MYSQL);
9363 }
9364 }
9365 556877 case dd::enum_column_types::DECIMAL:
9366 case dd::enum_column_types::FLOAT:
9367 case dd::enum_column_types::DOUBLE:
9368 case dd::enum_column_types::NEWDECIMAL:
9369 case dd::enum_column_types::LONG:
9370 case dd::enum_column_types::LONGLONG:
9371 case dd::enum_column_types::TINY:
9372 case dd::enum_column_types::SHORT:
9373 case dd::enum_column_types::INT24:
9374 /* Types based on Field_num set unsigned flag from value stored
9375 in the data-dictionary (YEAR being the exception). */
9376
2/2
✓ Branch 0 taken 546088 times.
✓ Branch 1 taken 10789 times.
556877 if (is_unsigned) *unsigned_flag = DATA_UNSIGNED;
9377 switch (dd_type) {
9378 case dd::enum_column_types::DECIMAL:
9379 return (DATA_DECIMAL);
9380 17 case dd::enum_column_types::FLOAT:
9381 17 return (DATA_FLOAT);
9382 5 case dd::enum_column_types::DOUBLE:
9383 5 return (DATA_DOUBLE);
9384 14 case dd::enum_column_types::NEWDECIMAL:
9385 14 *charset_no = my_charset_bin.number;
9386 14 return (DATA_FIXBINARY);
9387 556841 default:
9388 556841 break;
9389 }
9390 556841 return (DATA_INT);
9391 14 case dd::enum_column_types::DATE:
9392 case dd::enum_column_types::NEWDATE:
9393 case dd::enum_column_types::TIME:
9394 case dd::enum_column_types::DATETIME:
9395 14 return (DATA_INT);
9396 3 case dd::enum_column_types::YEAR:
9397 case dd::enum_column_types::TIMESTAMP:
9398 /* MySQL always sets unsigned flag for YEAR and old TIMESTAMP type. */
9399 3 *unsigned_flag = DATA_UNSIGNED;
9400 3 return (DATA_INT);
9401 20 case dd::enum_column_types::TIME2:
9402 case dd::enum_column_types::DATETIME2:
9403 case dd::enum_column_types::TIMESTAMP2:
9404 20 *charset_no = my_charset_bin.number;
9405 20 return (DATA_FIXBINARY);
9406 case dd::enum_column_types::GEOMETRY:
9407 /* Field_geom::binary() is always true. */
9408 return (DATA_GEOMETRY);
9409 3 case dd::enum_column_types::TINY_BLOB:
9410 case dd::enum_column_types::MEDIUM_BLOB:
9411 case dd::enum_column_types::BLOB:
9412 case dd::enum_column_types::LONG_BLOB:
9413 3 *charset_no = field_charset->number;
9414
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (field_charset != &my_charset_bin) *binary_type = 0;
9415 3 return (DATA_BLOB);
9416 case dd::enum_column_types::JSON:
9417 /* JSON fields are stored as BLOBs.
9418 Field_json::binary() always returns true even though data in
9419 such columns are stored in UTF8. */
9420 *charset_no = my_charset_utf8mb4_bin.number;
9421 return (DATA_BLOB);
9422 case dd::enum_column_types::TYPE_NULL:
9423 /* Compatibility with get_innobase_type_from_mysql_type(). */
9424 *charset_no = field_charset->number;
9425 if (field_charset != &my_charset_bin) *binary_type = 0;
9426 break;
9427 default:
9428 ut_error;
9429 }
9430
9431 return (0);
9432 }
9433
9434 /** Reads an unsigned integer value < 64k from 2 bytes, in the little-endian
9435 storage format.
9436 @return value */
9437 86 static inline uint innobase_read_from_2_little_endian(
9438 const uchar *buf) /*!< in: from where to read */
9439 {
9440 86 return ((uint)((ulint)(buf[0]) + 256 * ((ulint)(buf[1]))));
9441 }
9442
9443 /** Determines if a field is needed in a m_prebuilt struct 'template'.
9444 @return field to use, or NULL if the field is not needed */
9445 1541892974 static const Field *build_template_needs_field(
9446 bool index_contains, /*!< in:
9447 dict_index_contains_col_or_prefix(
9448 index, i) */
9449 bool read_just_key, /*!< in: true when MySQL calls
9450 ha_innobase::extra with the
9451 argument HA_EXTRA_KEYREAD; it is enough
9452 to read just columns defined in
9453 the index (i.e., no read of the
9454 clustered index record necessary) */
9455 bool fetch_all_in_key,
9456 /*!< in: true=fetch all fields in
9457 the index */
9458 bool fetch_primary_key_cols,
9459 /*!< in: true=fetch the
9460 primary key columns */
9461 dict_index_t *index, /*!< in: InnoDB index to use */
9462 const TABLE *table, /*!< in: MySQL table object */
9463 ulint i, /*!< in: field index in InnoDB table */
9464 ulint num_v) /*!< in: num virtual column so far */
9465 {
9466 1541892974 const Field *field = table->field[i];
9467
9468
2/2
✓ Branch 0 taken 876323598 times.
✓ Branch 1 taken 665569376 times.
1541892974 if (!index_contains) {
9469
2/2
✓ Branch 0 taken 5650562 times.
✓ Branch 1 taken 870673036 times.
876323598 if (read_just_key) {
9470 /* If this is a 'key read', we do not need
9471 columns that are not in the key */
9472
9473 5650562 return (nullptr);
9474 }
9475
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665569376 times.
665569376 } else if (fetch_all_in_key) {
9476 /* This field is needed in the query */
9477
9478 return (field);
9479 }
9480
9481
6/6
✓ Branch 0 taken 53893996 times.
✓ Branch 1 taken 1482350376 times.
✓ Branch 2 taken 516012 times.
✓ Branch 3 taken 53379132 times.
✓ Branch 4 taken 1482866432 times.
✓ Branch 5 taken 53379088 times.
1590137556 if (bitmap_is_set(table->read_set, static_cast<uint>(i)) ||
9482 53893996 bitmap_is_set(table->write_set, static_cast<uint>(i))) {
9483 /* This field is needed in the query */
9484
9485 1482866432 return (field);
9486 }
9487
9488
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53379095 times.
53379088 ut_ad(i >= num_v);
9489
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 53379095 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 53379095 times.
53379095 if (fetch_primary_key_cols &&
9490 dict_table_col_in_clustered_key(index->table, i - num_v)) {
9491 /* This field is needed in the query */
9492
9493 return (field);
9494 }
9495
9496 /* This field is not needed in the query, skip it */
9497
9498 53379095 return (nullptr);
9499 }
9500
9501 /** Determines if a field is needed in a m_prebuilt struct 'template'.
9502 @return whether the field is needed for index condition pushdown */
9503 49930 inline bool build_template_needs_field_in_icp(
9504 const dict_index_t *index, /*!< in: InnoDB index */
9505 const row_prebuilt_t *prebuilt, /*!< in: row fetch template */
9506 bool contains, /*!< in: whether the index contains
9507 column i */
9508 ulint i, /*!< in: column number */
9509 bool is_virtual)
9510 /*!< in: a virtual column or not */
9511 {
9512
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49930 times.
49930 ut_ad(contains == dict_index_contains_col_or_prefix(index, i, is_virtual));
9513
9514
2/2
✓ Branch 0 taken 49522 times.
✓ Branch 1 taken 408 times.
49930 return (index == prebuilt->index ? contains
9515 408 : dict_index_contains_col_or_prefix(
9516 50338 prebuilt->index, i, is_virtual));
9517 }
9518
9519 /** Adds a field to a m_prebuilt struct 'template'.
9520 @return the field template */
9521 2005649955 static mysql_row_templ_t *build_template_field(
9522 row_prebuilt_t *prebuilt, /*!< in/out: template */
9523 dict_index_t *clust_index, /*!< in: InnoDB clustered index */
9524 dict_index_t *index, /*!< in: InnoDB index to use */
9525 TABLE *table, /*!< in: MySQL table object */
9526 const Field *field, /*!< in: field in MySQL table */
9527 ulint i, /*!< in: field index in InnoDB table */
9528 ulint v_no) /*!< in: field index for virtual col */
9529 {
9530 mysql_row_templ_t *templ;
9531 const dict_col_t *col;
9532
9533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2005649789 times.
2005649955 ut_ad(clust_index->table == index->table);
9534
9535 2005649789 templ = prebuilt->mysql_template + prebuilt->n_template++;
9536 UNIV_MEM_INVALID(templ, sizeof *templ);
9537
9538
4/4
✓ Branch 0 taken 257477 times.
✓ Branch 1 taken 2005392312 times.
✓ Branch 2 taken 236632 times.
✓ Branch 3 taken 20845 times.
2005649789 if (innobase_is_v_fld(field)) {
9539 236632 templ->is_virtual = true;
9540 236632 col = &dict_table_get_nth_v_col(index->table, v_no)->m_col;
9541 } else {
9542 2005413157 templ->is_virtual = false;
9543 2005413157 col = index->table->get_col(i);
9544 }
9545
9546
2/2
✓ Branch 0 taken 2005411974 times.
✓ Branch 1 taken 236582 times.
2005648556 if (!templ->is_virtual) {
9547 2005411974 templ->col_no = i;
9548 2005411974 templ->clust_rec_field_no = dict_col_get_clust_pos(col, clust_index);
9549
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2005419285 times.
2005420317 ut_a(templ->clust_rec_field_no != ULINT_UNDEFINED);
9550 2005419285 templ->rec_prefix_field_no = ULINT_UNDEFINED;
9551
9552
2/2
✓ Branch 0 taken 938467652 times.
✓ Branch 1 taken 1066950100 times.
2005419285 if (index->is_clustered()) {
9553 938467652 templ->rec_field_is_prefix = false;
9554 938467652 templ->rec_field_no = templ->clust_rec_field_no;
9555 } else {
9556 /* If we're in a secondary index, keep track of the original index
9557 position even if this is just a prefix non-geometry index; we will use
9558 this later to avoid a cluster index lookup in some cases. */
9559
9560 1066950478 templ->rec_field_no = index->get_col_pos(
9561 i, false, false,
9562
2/2
✓ Branch 0 taken 1066950163 times.
✓ Branch 1 taken 315 times.
1066950100 (field->type() == MYSQL_TYPE_GEOMETRY) ? nullptr
9563 : &templ->rec_prefix_field_no);
9564 1066947989 templ->rec_field_is_prefix =
9565
2/2
✓ Branch 0 taken 853158613 times.
✓ Branch 1 taken 213789376 times.
1920106602 (templ->rec_field_no == ULINT_UNDEFINED) &&
9566
2/2
✓ Branch 0 taken 1886 times.
✓ Branch 1 taken 853156727 times.
853158613 (templ->rec_prefix_field_no != ULINT_UNDEFINED);
9567 #ifdef UNIV_DEBUG
9568
2/2
✓ Branch 0 taken 213792039 times.
✓ Branch 1 taken 853155950 times.
1066947989 if (templ->rec_prefix_field_no != ULINT_UNDEFINED) {
9569 213792039 const auto *const field = index->get_field(templ->rec_prefix_field_no);
9570
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 213791962 times.
213791979 ut_ad(templ->rec_field_is_prefix == (field->prefix_len != 0));
9571 } else {
9572
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 853157403 times.
853155950 ut_ad(!templ->rec_field_is_prefix);
9573 }
9574 #endif
9575 }
9576 } else {
9577 236582 templ->clust_rec_field_no = v_no;
9578 // Prefix optimisation on generated column indexes is not
9579 // currently supported
9580 236582 templ->rec_field_is_prefix = false;
9581 236582 templ->rec_prefix_field_no = ULINT_UNDEFINED;
9582
2/2
✓ Branch 0 taken 234719 times.
✓ Branch 1 taken 1913 times.
236582 if (index->is_clustered()) {
9583 234719 templ->rec_field_no = templ->clust_rec_field_no;
9584 } else {
9585 1913 templ->rec_field_no = index->get_col_pos(v_no, false, true);
9586 }
9587 }
9588
9589 /* Set in set_templ_icp(). */
9590 2005653649 templ->icp_rec_field_no = ULINT_UNDEFINED;
9591
9592
2/2
✓ Branch 0 taken 910002280 times.
✓ Branch 1 taken 1095649524 times.
2005653649 if (field->is_nullable()) {
9593 910002280 templ->mysql_null_byte_offset = field->null_offset();
9594
9595 910005656 templ->mysql_null_bit_mask = (ulint)field->null_bit;
9596 } else {
9597 1095649524 templ->mysql_null_bit_mask = 0;
9598 }
9599
9600 2005655180 templ->mysql_col_offset = (ulint)get_field_offset(table, field);
9601 2005651203 templ->mysql_col_len = (ulint)field->pack_length();
9602
6/6
✓ Branch 0 taken 236632 times.
✓ Branch 1 taken 2005411655 times.
✓ Branch 2 taken 2139 times.
✓ Branch 3 taken 234493 times.
✓ Branch 4 taken 2139 times.
✓ Branch 5 taken 2005646148 times.
2005648287 if (templ->is_virtual && innobase_is_multi_value_fld(field)) {
9603 2139 templ->mysql_mvidx_len = static_cast<ulint>(field->key_length());
9604 2139 templ->is_multi_val = true;
9605 } else {
9606 2005646148 templ->mysql_mvidx_len = 0;
9607 2005646148 templ->is_multi_val = false;
9608 }
9609 2005648287 templ->type = col->mtype;
9610 2005648287 templ->mysql_type = (ulint)field->type();
9611
9612
2/2
✓ Branch 0 taken 408155829 times.
✓ Branch 1 taken 1597492622 times.
2005648451 if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
9613 408155829 templ->mysql_length_bytes = field->get_length_bytes();
9614 } else {
9615 1597492622 templ->mysql_length_bytes = 0;
9616 }
9617
9618 2005652121 templ->charset = dtype_get_charset_coll(col->prtype);
9619 2005648967 templ->mbminlen = col->get_mbminlen();
9620 2005649173 templ->mbmaxlen = col->get_mbmaxlen();
9621 2005650434 templ->is_unsigned = col->prtype & DATA_UNSIGNED;
9622 2005650434 templ->compressed = (field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED);
9623 2005650090 templ->zip_dict_data = field->zip_dict_data;
9624
9625
6/6
✓ Branch 0 taken 1066950448 times.
✓ Branch 1 taken 938701815 times.
✓ Branch 2 taken 853159622 times.
✓ Branch 3 taken 213790826 times.
✓ Branch 4 taken 853159629 times.
✓ Branch 5 taken 1152492634 times.
2005650090 if (!index->is_clustered() && templ->rec_field_no == ULINT_UNDEFINED) {
9626 853159629 prebuilt->need_to_access_clustered = true;
9627 }
9628
9629 /* For spatial index, we need to access cluster index. */
9630
2/2
✓ Branch 0 taken 692 times.
✓ Branch 1 taken 2005645738 times.
2005652263 if (dict_index_is_spatial(index)) {
9631 692 prebuilt->need_to_access_clustered = true;
9632 }
9633
9634 2005646430 if (prebuilt->mysql_prefix_len <
9635
2/2
✓ Branch 0 taken 2005596811 times.
✓ Branch 1 taken 49619 times.
2005646430 templ->mysql_col_offset + templ->mysql_col_len) {
9636 2005596811 prebuilt->mysql_prefix_len = templ->mysql_col_offset + templ->mysql_col_len;
9637 }
9638
9639
2/2
✓ Branch 0 taken 410448216 times.
✓ Branch 1 taken 1595198342 times.
2005646430 if (DATA_LARGE_MTYPE(templ->type)) {
9640 410448216 prebuilt->templ_contains_blob = true;
9641 }
9642
9643
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2005646558 times.
2005646558 if (templ->type == DATA_POINT) {
9644 /* We set this only when it's DATA_POINT, but not
9645 DATA_VAR_POINT */
9646 prebuilt->templ_contains_fixed_point = true;
9647 }
9648
9649 2005646558 return (templ);
9650 }
9651
9652 /** Set Index Condition Push down (ICP) field number in template.
9653 @param[in,out] templ mysql column template
9654 @param[in] index index used to build the template
9655 @param[in] scan_index active index for current scan
9656 @param[in] col_position position of current column */
9657 11151 static void set_templ_icp(mysql_row_templ_t *templ, const dict_index_t *index,
9658 const dict_index_t *scan_index, ulint col_position) {
9659
2/4
✓ Branch 0 taken 11151 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11151 times.
11151 if (scan_index == nullptr || templ == nullptr) {
9660 return;
9661 }
9662
9663 11151 bool is_virtual = templ->is_virtual;
9664 11151 auto icp_field_no = templ->rec_field_no;
9665
9666
2/2
✓ Branch 0 taken 384 times.
✓ Branch 1 taken 10767 times.
11151 if (scan_index != index) {
9667 /* First, try to find the column position without prefix. */
9668 384 icp_field_no = scan_index->get_col_pos(col_position, false, is_virtual);
9669 }
9670
9671 /* Try any prefix of the column. Used in end_range comparison. */
9672
2/2
✓ Branch 0 taken 420 times.
✓ Branch 1 taken 10731 times.
11151 if (icp_field_no == ULINT_UNDEFINED) {
9673
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 420 times.
420 ut_ad(!scan_index->is_clustered());
9674 420 icp_field_no = scan_index->get_col_pos(col_position, true, is_virtual);
9675 }
9676 11151 templ->icp_rec_field_no = icp_field_no;
9677 }
9678
9679 /** Builds a 'template' to the m_prebuilt struct. The template is used in fast
9680 retrieval of just those column values MySQL needs in its processing.
9681 @param[in] whole_row true if access is needed to a whole row, false if accessing
9682 individual fields is enough */
9683 162851575 void ha_innobase::build_template(bool whole_row) {
9684 dict_index_t *index;
9685 dict_index_t *clust_index;
9686 ulint n_fields;
9687 162851575 bool fetch_all_in_key = false;
9688 162851575 bool fetch_primary_key_cols = false;
9689 ulint i;
9690
9691
2/2
✓ Branch 0 taken 38017640 times.
✓ Branch 1 taken 124833935 times.
162851575 if (m_prebuilt->select_lock_type == LOCK_X) {
9692 /* We always retrieve the whole clustered index record if we
9693 use exclusive row level locks, for example, if the read is
9694 done in an UPDATE statement. */
9695
9696 38017640 whole_row = true;
9697
2/2
✓ Branch 0 taken 124743965 times.
✓ Branch 1 taken 89970 times.
124833935 } else if (!whole_row) {
9698
2/2
✓ Branch 0 taken 240 times.
✓ Branch 1 taken 124743725 times.
124743965 if (m_prebuilt->hint_need_to_fetch_extra_cols == ROW_RETRIEVE_ALL_COLS) {
9699 /* We know we must at least fetch all columns in the
9700 key, or all columns in the table */
9701
9702
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 240 times.
240 if (m_prebuilt->read_just_key) {
9703 /* MySQL has instructed us that it is enough
9704 to fetch the columns in the key; looks like
9705 MySQL can set this flag also when there is
9706 only a prefix of the column in the key: in
9707 that case we retrieve the whole column from
9708 the clustered index */
9709
9710 fetch_all_in_key = true;
9711 } else {
9712 240 whole_row = true;
9713 }
9714
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 124743725 times.
124743725 } else if (m_prebuilt->hint_need_to_fetch_extra_cols ==
9715 ROW_RETRIEVE_PRIMARY_KEY) {
9716 /* We must at least fetch all primary key cols. Note
9717 that if the clustered index was internally generated
9718 by InnoDB on the row id (no primary key was
9719 defined), then row_search_for_mysql() will always
9720 retrieve the row id to a special buffer in the
9721 m_prebuilt struct. */
9722
9723 fetch_primary_key_cols = true;
9724 }
9725 }
9726
9727 162851575 clust_index = m_prebuilt->table->first_index();
9728
9729
2/2
✓ Branch 0 taken 38108151 times.
✓ Branch 1 taken 124743794 times.
162851945 index = whole_row ? clust_index : m_prebuilt->index;
9730
9731 162851945 m_prebuilt->need_to_access_clustered = (index == clust_index);
9732
9733 /* Either m_prebuilt->index should be a secondary index, or it
9734 should be the clustered index. */
9735
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 162851897 times.
162851945 ut_ad(index->is_clustered() == (index == clust_index));
9736
9737 /* Below we check column by column if we need to access
9738 the clustered index. */
9739
9740 162851897 n_fields = (ulint)table->s->fields; /* number of columns */
9741
9742
2/2
✓ Branch 0 taken 3351150 times.
✓ Branch 1 taken 159500747 times.
162851897 if (!m_prebuilt->mysql_template) {
9743 3351148 m_prebuilt->mysql_template = (mysql_row_templ_t *)ut::malloc_withkey(
9744 3351150 UT_NEW_THIS_FILE_PSI_KEY, n_fields * sizeof(mysql_row_templ_t));
9745 }
9746
9747 #if defined(UNIV_DEBUG) && !defined(UNIV_DEBUG_VALGRIND)
9748 /* zero-filling for compare contents for debug */
9749 162851548 memset(m_prebuilt->mysql_template, 0, n_fields * sizeof(mysql_row_templ_t));
9750 #endif /* UNIV_DEBUG && !UNIV_DEBUG_VALGRIND */
9751
9752 162851548 m_prebuilt->template_type =
9753
2/2
✓ Branch 0 taken 38107892 times.
✓ Branch 1 taken 124743656 times.
162851548 whole_row ? ROW_MYSQL_WHOLE_ROW : ROW_MYSQL_REC_FIELDS;
9754 162851548 m_prebuilt->null_bitmap_len = table->s->null_bytes;
9755
9756 /* Prepare to build m_prebuilt->mysql_template[]. */
9757 162851548 m_prebuilt->templ_contains_blob = false;
9758 162851548 m_prebuilt->templ_contains_fixed_point = false;
9759 162851548 m_prebuilt->mysql_prefix_len = 0;
9760 162851548 m_prebuilt->n_template = 0;
9761 162851548 m_prebuilt->idx_cond_n_cols = 0;
9762
9763 /* Note that in InnoDB, i is the column number in the table.
9764 MySQL calls columns 'fields'. */
9765
9766
4/4
✓ Branch 0 taken 153197995 times.
✓ Branch 1 taken 9653553 times.
✓ Branch 2 taken 5287 times.
✓ Branch 3 taken 153192708 times.
162851548 if (active_index != MAX_KEY && active_index == pushed_idx_cond_keyno) {
9767 5287 ulint num_v = 0;
9768
9769 /* Push down an index condition or an end_range check. */
9770
2/2
✓ Branch 0 taken 24965 times.
✓ Branch 1 taken 5287 times.
30252 for (i = 0; i < n_fields; i++) {
9771 bool index_contains;
9772
9773
4/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 24937 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 10 times.
24965 if (innobase_is_v_fld(table->field[i])) {
9774 18 index_contains = dict_index_contains_col_or_prefix(index, num_v, true);
9775 } else {
9776 index_contains =
9777 24947 dict_index_contains_col_or_prefix(index, i - num_v, false);
9778 }
9779
9780 /* Test if an end_range or an index condition
9781 refers to the field. Note that "index" and
9782 "index_contains" may refer to the clustered index.
9783 Index condition pushdown is relative to
9784 m_prebuilt->index (the index that is being
9785 looked up first). */
9786
9787 /* When join_read_always_key() invokes this
9788 code via handler::ha_index_init() and
9789 ha_innobase::index_init(), end_range is not
9790 yet initialized. Because of that, we must
9791 always check for index_contains, instead of
9792 the subset
9793 field->part_of_key.is_set(active_index)
9794 which would be acceptable if end_range==NULL. */
9795
4/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 24937 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 10 times.
24965 bool is_v = innobase_is_v_fld(table->field[i]);
9796
4/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 24947 times.
✓ Branch 2 taken 10095 times.
✓ Branch 3 taken 14870 times.
24965 if (build_template_needs_field_in_icp(index, m_prebuilt, index_contains,
9797 is_v ? num_v : i - num_v, is_v)) {
9798 /* Needed in ICP */
9799 const Field *field;
9800 mysql_row_templ_t *templ;
9801
9802
2/2
✓ Branch 0 taken 148 times.
✓ Branch 1 taken 9947 times.
10095 if (whole_row) {
9803 148 field = table->field[i];
9804 } else {
9805 19894 field = build_template_needs_field(
9806 9947 index_contains, m_prebuilt->read_just_key, fetch_all_in_key,
9807 9947 fetch_primary_key_cols, index, table, i, num_v);
9808
2/2
✓ Branch 0 taken 1079 times.
✓ Branch 1 taken 8868 times.
9947 if (!field) {
9809
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1079 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1079 if (innobase_is_v_fld(table->field[i])) {
9810 num_v++;
9811 }
9812 1079 continue;
9813 }
9814 }
9815
9816 9016 templ = build_template_field(m_prebuilt, clust_index, index, table,
9817 field, i - num_v, 0);
9818
9819
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9016 times.
9016 ut_ad(!templ->is_virtual);
9820
9821 9016 m_prebuilt->idx_cond_n_cols++;
9822
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9016 times.
9016 ut_ad(m_prebuilt->idx_cond_n_cols == m_prebuilt->n_template);
9823
9824 9016 auto column_position = i - num_v;
9825
9826 9016 set_templ_icp(templ, index, m_prebuilt->index, column_position);
9827
9828
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9016 times.
9016 ut_ad(templ->icp_rec_field_no != ULINT_UNDEFINED);
9829
9830 /* Index condition pushdown can be used on
9831 all columns of a secondary index, and on
9832 the PRIMARY KEY columns. On the clustered
9833 index, it must never be used on other than
9834 PRIMARY KEY columns, because those columns
9835 may be stored off-page, and we will not
9836 fetch externally stored columns before
9837 checking the index condition. */
9838 /* TODO: test the above with an assertion
9839 like this. Note that index conditions are
9840 currently pushed down as part of the
9841 "optimizer phase" while end_range is done
9842 as part of the execution phase. Therefore,
9843 we were unable to use an accurate condition
9844 for end_range in the "if" condition above,
9845 and the following assertion would fail.
9846 ut_ad(!(m_prebuilt->index->is_clustered())
9847 || templ->rec_field_no
9848 < m_prebuilt->index->n_uniq);
9849 */
9850 }
9851
9852
4/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 23858 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 10 times.
23886 if (innobase_is_v_fld(table->field[i])) {
9853 18 num_v++;
9854 }
9855 }
9856
9857
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5287 times.
5287 ut_ad(m_prebuilt->idx_cond_n_cols > 0);
9858
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5287 times.
5287 ut_ad(m_prebuilt->idx_cond_n_cols == m_prebuilt->n_template);
9859
9860 5287 num_v = 0;
9861
9862 /* Include the fields that are not needed in index condition
9863 pushdown. */
9864
2/2
✓ Branch 0 taken 24965 times.
✓ Branch 1 taken 5287 times.
30252 for (i = 0; i < n_fields; i++) {
9865 mysql_row_templ_t *templ;
9866 bool index_contains;
9867
9868
4/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 24937 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 10 times.
24965 if (innobase_is_v_fld(table->field[i])) {
9869 18 index_contains = dict_index_contains_col_or_prefix(index, num_v, true);
9870 } else {
9871 index_contains =
9872 24947 dict_index_contains_col_or_prefix(index, i - num_v, false);
9873 }
9874
9875
4/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 24937 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 10 times.
24965 bool is_v = innobase_is_v_fld(table->field[i]);
9876
9877
4/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 24947 times.
✓ Branch 2 taken 14870 times.
✓ Branch 3 taken 10095 times.
24965 if (!build_template_needs_field_in_icp(index, m_prebuilt, index_contains,
9878 is_v ? num_v : i - num_v, is_v)) {
9879 /* Not needed in ICP */
9880 const Field *field;
9881
9882
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 14814 times.
14870 if (whole_row) {
9883 56 field = table->field[i];
9884 } else {
9885 29628 field = build_template_needs_field(
9886 14814 index_contains, m_prebuilt->read_just_key, fetch_all_in_key,
9887 14814 fetch_primary_key_cols, index, table, i, num_v);
9888
2/2
✓ Branch 0 taken 3570 times.
✓ Branch 1 taken 11244 times.
14814 if (!field) {
9889
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3566 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
3570 if (innobase_is_v_fld(table->field[i])) {
9890 4 num_v++;
9891 }
9892 3570 continue;
9893 }
9894 }
9895
9896 11300 templ = build_template_field(m_prebuilt, clust_index, index, table,
9897 field, i - num_v, num_v);
9898
9899
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 11286 times.
11300 if (templ->is_virtual) {
9900 14 num_v++;
9901 }
9902 }
9903 }
9904
9905 5287 m_prebuilt->idx_cond = true;
9906 5287 } else {
9907 mysql_row_templ_t *templ;
9908 162846261 ulint num_v = 0;
9909 /* No index condition pushdown */
9910 162846261 m_prebuilt->idx_cond = false;
9911
9912
2/2
✓ Branch 0 taken 2064651392 times.
✓ Branch 1 taken 162843332 times.
2227494724 for (i = 0; i < n_fields; i++) {
9913 const Field *field;
9914
4/4
✓ Branch 0 taken 437633 times.
✓ Branch 1 taken 2064213759 times.
✓ Branch 2 taken 413096 times.
✓ Branch 3 taken 24537 times.
2064651392 bool is_virtual = innobase_is_v_fld(table->field[i]);
9915
9916
2/2
✓ Branch 0 taken 522783559 times.
✓ Branch 1 taken 1541867833 times.
2064651392 if (whole_row) {
9917 /* Even this is whole_row, if the seach is
9918 on a virtual column, and read_just_key is
9919 set, and field is not in this index, we
9920 will not try to fill the value since they
9921 are not stored in such index nor in the
9922 cluster index. */
9923
5/6
✓ Branch 0 taken 55586 times.
✓ Branch 1 taken 522727973 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 55580 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 522783559 times.
522783565 if (is_virtual && m_prebuilt->read_just_key &&
9924
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 !dict_index_contains_col_or_prefix(m_prebuilt->index, num_v,
9925 true)) {
9926 /* Turn off ROW_MYSQL_WHOLE_ROW */
9927 m_prebuilt->template_type = ROW_MYSQL_REC_FIELDS;
9928 num_v++;
9929 continue;
9930 }
9931
9932 522783559 field = table->field[i];
9933 } else {
9934 bool contain;
9935
9936
4/4
✓ Branch 0 taken 364504 times.
✓ Branch 1 taken 1541503329 times.
✓ Branch 2 taken 357510 times.
✓ Branch 3 taken 6994 times.
1541867833 if (innobase_is_v_fld(table->field[i])) {
9937 357510 contain = dict_index_contains_col_or_prefix(index, num_v, true);
9938 } else {
9939 1541510323 contain = dict_index_contains_col_or_prefix(index, i - num_v, false);
9940 }
9941
9942 3083735869 field = build_template_needs_field(
9943 1541866498 contain, m_prebuilt->read_just_key, fetch_all_in_key,
9944 1541866498 fetch_primary_key_cols, index, table, i, num_v);
9945
2/2
✓ Branch 0 taken 59024527 times.
✓ Branch 1 taken 1482844844 times.
1541869371 if (!field) {
9946
2/2
✓ Branch 0 taken 176478 times.
✓ Branch 1 taken 58848049 times.
59024527 if (is_virtual) {
9947 176478 num_v++;
9948 }
9949 59024527 continue;
9950 }
9951 }
9952
9953 2005628403 templ = build_template_field(m_prebuilt, clust_index, index, table, field,
9954 i - num_v, num_v);
9955
9956 /* Virtual columns may have to be read from the secondary index before
9957 evaluating an end-range condition in row_search_end_range_check(). Set
9958 ICP field number for virtual column. */
9959 2005626126 auto scan_index = m_prebuilt->index;
9960
4/4
✓ Branch 0 taken 2002875211 times.
✓ Branch 1 taken 2750915 times.
✓ Branch 2 taken 1122010052 times.
✓ Branch 3 taken 880865889 times.
2005626126 bool is_sec_idx = (scan_index != nullptr && !scan_index->is_clustered());
9961
9962
4/4
✓ Branch 0 taken 236618 times.
✓ Branch 1 taken 2005390238 times.
✓ Branch 2 taken 2135 times.
✓ Branch 3 taken 234483 times.
2005626856 if (is_virtual && is_sec_idx) {
9963 2135 set_templ_icp(templ, index, scan_index, num_v);
9964 }
9965
9966
2/2
✓ Branch 0 taken 236618 times.
✓ Branch 1 taken 2005387318 times.
2005623936 if (templ->is_virtual) {
9967 236618 num_v++;
9968 }
9969 }
9970 }
9971
9972
4/4
✓ Branch 0 taken 64843957 times.
✓ Branch 1 taken 98004662 times.
✓ Branch 2 taken 60657791 times.
✓ Branch 3 taken 4186166 times.
162848619 if (index != clust_index && m_prebuilt->need_to_access_clustered) {
9973 /* Change rec_field_no's to correspond to the clustered index
9974 record */
9975
2/2
✓ Branch 0 taken 1054546849 times.
✓ Branch 1 taken 60657791 times.
1115204640 for (i = 0; i < m_prebuilt->n_template; i++) {
9976 1054546849 mysql_row_templ_t *templ = &m_prebuilt->mysql_template[i];
9977
9978 1054546849 templ->rec_field_no = templ->clust_rec_field_no;
9979 }
9980 }
9981 162848619 }
9982
9983 /** This special handling is really to overcome the limitations of MySQL's
9984 binlogging. We need to eliminate the non-determinism that will arise in
9985 INSERT ... SELECT type of statements, since MySQL binlog only stores the
9986 min value of the autoinc interval. Once that is fixed we can get rid of
9987 the special lock handling.
9988 @return DB_SUCCESS if all OK else error code */
9989
9990 8497243 dberr_t ha_innobase::innobase_lock_autoinc(void) {
9991
1/2
✓ Branch 0 taken 8497429 times.
✗ Branch 1 not taken.
8497243 DBUG_TRACE;
9992 8497429 dberr_t error = DB_SUCCESS;
9993 8497429 long lock_mode = innobase_autoinc_lock_mode;
9994
9995
2/8
✗ Branch 0 not taken.
✓ Branch 1 taken 8497429 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 8497344 times.
8497429 ut_ad(!srv_read_only_mode || m_prebuilt->table->is_intrinsic());
9996
9997
7/8
✓ Branch 0 taken 8497402 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8497310 times.
✓ Branch 3 taken 92 times.
✓ Branch 4 taken 6604787 times.
✓ Branch 5 taken 1892523 times.
✓ Branch 6 taken 6604818 times.
✓ Branch 7 taken 1892584 times.
8497344 if (m_prebuilt->table->is_intrinsic() || m_prebuilt->no_autoinc_locking) {
9998 /* Intrinsic table are not shared across connection
9999 so there is no need to AUTOINC lock the table.
10000 Also we won't use AUTOINC lock if this was requested
10001 explicitly. */
10002 6604818 lock_mode = AUTOINC_NO_LOCKING;
10003 }
10004
10005
3/4
✓ Branch 0 taken 8487356 times.
✓ Branch 1 taken 1003 times.
✓ Branch 2 taken 9043 times.
✗ Branch 3 not taken.
8497402 switch (lock_mode) {
10006 8487356 case AUTOINC_NO_LOCKING:
10007 /* Acquire only the AUTOINC mutex. */
10008
1/2
✓ Branch 0 taken 8487399 times.
✗ Branch 1 not taken.
8487356 dict_table_autoinc_lock(m_prebuilt->table);
10009 8487399 break;
10010
10011 1003 case AUTOINC_NEW_STYLE_LOCKING:
10012 /* For simple (single/multi) row INSERTs, we fallback to the
10013 old style only if another transaction has already acquired
10014 the AUTOINC lock on behalf of a LOAD FILE or INSERT ... SELECT
10015 etc. type of statement. */
10016
5/6
✓ Branch 0 taken 1003 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 315 times.
✓ Branch 3 taken 688 times.
✓ Branch 4 taken 687 times.
✓ Branch 5 taken 316 times.
1318 if (thd_sql_command(m_user_thd) == SQLCOM_INSERT ||
10017
2/4
✓ Branch 0 taken 315 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 315 times.
315 thd_sql_command(m_user_thd) == SQLCOM_REPLACE) {
10018 687 dict_table_t *ib_table = m_prebuilt->table;
10019
10020 /* Acquire the AUTOINC mutex. */
10021
1/2
✓ Branch 0 taken 688 times.
✗ Branch 1 not taken.
687 dict_table_autoinc_lock(ib_table);
10022
10023
2/4
✓ Branch 0 taken 688 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 688 times.
✗ Branch 3 not taken.
688 DEBUG_SYNC_C("innobase_lock_autoinc");
10024
10025 /* We need to check that another transaction isn't
10026 already holding the AUTOINC lock on the table. */
10027
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 688 times.
688 if (ib_table->count_by_mode[LOCK_AUTO_INC]) {
10028 /* Release the mutex to avoid deadlocks. */
10029 dict_table_autoinc_unlock(ib_table);
10030 } else {
10031 688 break;
10032 }
10033 }
10034 /* Fall through to old style locking. */
10035 [[fallthrough]];
10036
10037 case AUTOINC_OLD_STYLE_LOCKING:
10038
2/4
✓ Branch 0 taken 9312 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9312 times.
9359 DBUG_EXECUTE_IF("die_if_autoinc_old_lock_style_used", ut_d(ut_error););
10039
1/2
✓ Branch 0 taken 9314 times.
✗ Branch 1 not taken.
9312 error = row_lock_table_autoinc_for_mysql(m_prebuilt);
10040
10041
2/2
✓ Branch 0 taken 9313 times.
✓ Branch 1 taken 1 times.
9314 if (error == DB_SUCCESS) {
10042 /* Acquire the AUTOINC mutex. */
10043
1/2
✓ Branch 0 taken 9313 times.
✗ Branch 1 not taken.
9313 dict_table_autoinc_lock(m_prebuilt->table);
10044 }
10045 9314 break;
10046
10047 default:
10048 ut_error;
10049 }
10050
10051 8497430 return error;
10052 8497401 }
10053
10054 /** Store the autoinc value in the table. The autoinc value is only set if
10055 it's greater than the existing autoinc value in the table.
10056 @return DB_SUCCESS if all went well else error code */
10057
10058 1439762 dberr_t ha_innobase::innobase_set_max_autoinc(
10059 ulonglong auto_inc) /*!< in: value to store */
10060 {
10061 dberr_t error;
10062
10063 1439762 error = innobase_lock_autoinc();
10064
10065
1/2
✓ Branch 0 taken 1439762 times.
✗ Branch 1 not taken.
1439762 if (error == DB_SUCCESS) {
10066 1439762 dict_table_autoinc_update_if_greater(m_prebuilt->table, auto_inc);
10067
10068 1439762 dict_table_autoinc_unlock(m_prebuilt->table);
10069 }
10070
10071 1439762 return (error);
10072 }
10073
10074 /** Write Row interface optimized for intrinisc table.
10075 @param[in] record a row in MySQL format.
10076 @return 0 on success or error code */
10077 13654241 int ha_innobase::intrinsic_table_write_row(uchar *record) {
10078 dberr_t err;
10079
10080 /* No auto-increment support for intrinsic table. */
10081
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 13654241 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 13654241 times.
13654241 ut_ad(!(table->next_number_field && record == table->record[0]));
10082
10083
2/2
✓ Branch 0 taken 13600439 times.
✓ Branch 1 taken 53802 times.
13654241 if (m_prebuilt->mysql_template == nullptr ||
10084
2/2
✓ Branch 0 taken 24730 times.
✓ Branch 1 taken 13575709 times.
13600439 m_prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) {
10085 /* Build the template used in converting quickly between
10086 the two database formats */
10087 78532 build_template(true);
10088 }
10089
10090 13654241 err = row_insert_for_mysql((byte *)record, m_prebuilt);
10091
10092 return (
10093 13654241 convert_error_code_to_mysql(err, m_prebuilt->table->flags, m_user_thd));
10094 }
10095
10096 /** Parse out multi-value and store in a multi_value_data struct
10097 @param[in] bv JSON binary that has the mult-value
10098 @param[out] valuep store the parsed out value
10099 @param[in] fld Array Field for the data
10100 @param[in] dfield InnoDB indexed field struct
10101 @param[in] comp if this is new InnoDB row type
10102 @param[in,out] heap heap memory */
10103 26278 static void innobase_store_multi_value_low(json_binary::Value *bv,
10104 multi_value_data **valuep,
10105 Field_typed_array *fld,
10106 dfield_t *dfield, ulint comp,
10107 mem_heap_t *heap) {
10108 26278 multi_value_data *value = *valuep;
10109 byte *buf;
10110
10111 /* Even for single values, there will be an array with 1 element */
10112
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26278 times.
26278 ut_ad(bv->type() == json_binary::Value::ARRAY);
10113 26278 uint32_t elements = bv->element_count();
10114
10115
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26278 times.
26278 ut_ad(elements > 0);
10116
10117
2/2
✓ Branch 0 taken 25587 times.
✓ Branch 1 taken 691 times.
26278 if (value == nullptr) {
10118
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25587 times.
25587 ut_ad(heap != nullptr);
10119 value =
10120 25587 static_cast<multi_value_data *>(mem_heap_zalloc(heap, sizeof(*value)));
10121 }
10122
10123
2/2
✓ Branch 0 taken 25588 times.
✓ Branch 1 taken 690 times.
26278 if (elements > value->num_alc) {
10124 25588 value->alloc(elements, false, heap);
10125 }
10126
10127 26278 buf = reinterpret_cast<byte *>(value->conv_buf);
10128
10129 26278 value->num_v = elements;
10130
10131 26278 ulint col_len = fld->key_length();
10132
10133
2/2
✓ Branch 0 taken 254894 times.
✓ Branch 1 taken 26278 times.
281172 for (uint i = 0; i < elements; i++) {
10134 254894 const byte *mysql_data = nullptr;
10135
1/2
✓ Branch 0 taken 254894 times.
✗ Branch 1 not taken.
254894 const dtype_t *dtype = dfield_get_type(dfield);
10136 254894 ulint type = dtype->mtype;
10137 int64_t val;
10138
10139
1/2
✓ Branch 0 taken 254894 times.
✗ Branch 1 not taken.
254894 json_binary::Value elt = bv->element(i);
10140
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 254894 times.
254894 if (elt.type() == json_binary::Value::LITERAL_NULL) {
10141 dfield_set_data(dfield, nullptr, UNIV_SQL_NULL);
10142
2/2
✓ Branch 0 taken 253459 times.
✓ Branch 1 taken 1435 times.
254894 } else if (type == DATA_INT) {
10143 byte data[8];
10144
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 253381 times.
253459 if (elt.type() == json_binary::Value::OPAQUE) {
10145
1/2
✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
156 if (elt.field_type() == MYSQL_TYPE_TIME ||
10146
3/6
✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 78 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 78 times.
156 elt.field_type() == MYSQL_TYPE_DATETIME ||
10147 78 elt.field_type() == MYSQL_TYPE_TIMESTAMP) {
10148 /* Newer Mysql temporal types use DATA_FIXBINARY Innodb type */
10149 ut_d(ut_error); /* purecov: inspected */
10150
1/2
✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
78 } else if (elt.field_type() == MYSQL_TYPE_DATE) {
10151 /* Temporal data has at most 8 bytes length */
10152
1/2
✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
78 Json_datetime::from_packed_to_key(elt.get_data(), elt.field_type(),
10153 78 data, fld->decimals());
10154 78 mysql_data = data;
10155 } else {
10156 mysql_data = reinterpret_cast<const byte *>(elt.get_data());
10157 }
10158 } else {
10159 /* Both signed and unsigned ints are handled here. Because there is
10160 an assumption the data passed from server should be always
10161 little-endian one, so need to convert it explicitly here.
10162 @see Field_longlong::store() */
10163
2/2
✓ Branch 0 taken 253101 times.
✓ Branch 1 taken 280 times.
253381 if (fld->is_unsigned()) {
10164 253101 val = static_cast<int64_t>(elt.get_uint64());
10165 } else {
10166 280 val = elt.get_int64();
10167 }
10168 #ifdef WORDS_BIGENDIAN
10169 if (fld->table->s->db_low_byte_first) {
10170 int8store(data, val);
10171 } else
10172 #endif
10173 {
10174 253381 longlongstore(data, val);
10175 }
10176 253381 mysql_data = data;
10177 }
10178
1/2
✓ Branch 0 taken 253459 times.
✗ Branch 1 not taken.
253459 row_mysql_store_col_in_innobase_format(dfield, buf, true, mysql_data,
10179 col_len, comp, false, nullptr, 0,
10180 nullptr);
10181
4/6
✓ Branch 0 taken 1435 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1435 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 549 times.
✓ Branch 5 taken 886 times.
1435 } else if (type == DATA_CHAR || type == DATA_VARCHAR ||
10182 type == DATA_VARMYSQL) {
10183 549 mysql_data = (byte *)elt.get_data();
10184 549 col_len = (ulint)elt.get_data_length();
10185
1/2
✓ Branch 0 taken 549 times.
✗ Branch 1 not taken.
549 dfield_set_data(dfield, mysql_data, col_len);
10186
3/4
✓ Branch 0 taken 494 times.
✓ Branch 1 taken 392 times.
✓ Branch 2 taken 494 times.
✗ Branch 3 not taken.
886 } else if (type == DATA_BINARY || type == DATA_FIXBINARY) {
10187
1/2
✓ Branch 0 taken 886 times.
✗ Branch 1 not taken.
886 if (elt.type() == json_binary::Value::OPAQUE) {
10188
3/4
✓ Branch 0 taken 392 times.
✓ Branch 1 taken 329 times.
✓ Branch 2 taken 165 times.
✗ Branch 3 not taken.
886 switch (elt.field_type()) {
10189 392 case MYSQL_TYPE_VARCHAR: {
10190 392 mysql_data = reinterpret_cast<const byte *>(elt.get_data());
10191
1/2
✓ Branch 0 taken 392 times.
✗ Branch 1 not taken.
392 dfield_set_data(dfield,
10192 392 reinterpret_cast<const byte *>(elt.get_data()),
10193 392 elt.get_data_length());
10194 392 break;
10195 }
10196 329 case MYSQL_TYPE_NEWDECIMAL: {
10197 329 ut_d(my_decimal d);
10198 /* Ensure correct decimal value */
10199
2/4
✓ Branch 0 taken 329 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 329 times.
329 ut_ad(!Json_decimal::convert_from_binary(
10200 elt.get_data(), elt.get_data_length(), &d));
10201 /* Ensure binary is of the expected size */
10202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 329 times.
329 ut_ad(Json_decimal::get_encoded_binary_len(elt.get_data_length()) ==
10203 dfield->type.len);
10204
1/2
✓ Branch 0 taken 329 times.
✗ Branch 1 not taken.
329 dfield_set_data(dfield,
10205 329 Json_decimal::get_encoded_binary(elt.get_data()),
10206 329 dfield->type.len);
10207 329 break;
10208 329 }
10209 165 case MYSQL_TYPE_TIME:
10210 case MYSQL_TYPE_DATE:
10211 case MYSQL_TYPE_DATETIME:
10212 case MYSQL_TYPE_TIMESTAMP: {
10213 /* Temporal data has at most 8 bytes length */
10214
1/2
✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
165 Json_datetime::from_packed_to_key(elt.get_data(), elt.field_type(),
10215 165 buf, fld->decimals());
10216
10217
1/2
✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
165 dfield_set_data(dfield, buf, dfield->type.len);
10218 165 break;
10219 }
10220 default:
10221 /* Shouldn't happen */
10222 ut_d(ut_error); /* purecov: inspected */
10223 }
10224 }
10225 886 } else {
10226 /* not supported */
10227 ut_d(ut_error); /* purecov: inspected */
10228 }
10229
10230 254894 value->datap[i] = dfield->data;
10231 254894 value->data_len[i] = dfield->len;
10232 254894 buf += sizeof(uint64_t);
10233 }
10234
10235 26278 *valuep = value;
10236 26278 }
10237
10238 /** Handle the multi-value array, parse the values and store them
10239 @param[in] v JSON binary that has the mult-value
10240 @param[out] value store the parsed out value
10241 @param[in] fld array Field for the data
10242 @param[in] dfield InnoDB indexed field struct
10243 @param[in] comp if this is new InnoDB row type
10244 @param[in,out] heap heap memory
10245 @return true if values are valid and stored, otherwise false */
10246 26330 static inline bool innobase_store_multi_value(json_binary::Value &v,
10247 multi_value_data *value,
10248 Field_typed_array *fld,
10249 dfield_t *dfield, bool comp,
10250 mem_heap_t *heap) {
10251
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26330 times.
26330 if (v.type() == json_binary::Value::ERROR) {
10252 /* purecov: begin inspected */
10253 my_error(ER_INVALID_JSON_BINARY_DATA, MYF(0));
10254 return (false);
10255 /* purecov: end */
10256
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 26309 times.
26330 } else if (v.type() == json_binary::Value::LITERAL_NULL) {
10257 /* When field is null, json parser creates LETERAL_NULL value.
10258 JSON NULL shouldn't get here in any other way */
10259
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 ut_ad(fld->is_null());
10260 21 dfield_set_null(dfield);
10261
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 26278 times.
26309 } else if (v.element_count() == 0) {
10262 31 dfield_set_data(dfield, nullptr, UNIV_NO_INDEX_VALUE);
10263 } else {
10264 26278 innobase_store_multi_value_low(&v, &value, fld, dfield, comp, heap);
10265 26278 dfield_set_data(dfield, value, UNIV_MULTI_VALUE_ARRAY_MARKER);
10266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26278 times.
26278 ut_ad(!value->duplicate());
10267 }
10268
10269 26330 return (true);
10270 }
10271
10272 /** Parse out multi-values from a MySQL record
10273 @param[in] mysql_table MySQL table structure
10274 @param[in] f_idx field index of the multi-value column
10275 @param[in,out] dfield field structure to store parsed multi-value
10276 @param[in,out] value nullptr or the multi-value structure
10277 to store the parsed values
10278 @param[in] old_val old value if exists
10279 @param[in] comp true if InnoDB table uses compact row format
10280 @param[in,out] heap memory heap */
10281 821 void innobase_get_multi_value(const TABLE *mysql_table, ulint f_idx,
10282 dfield_t *dfield, multi_value_data *value,
10283 uint old_val, ulint comp, mem_heap_t *heap) {
10284 Field_typed_array *fld;
10285 uint length;
10286 const char *ptr;
10287
10288
2/4
✓ Branch 0 taken 821 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 821 times.
821 ut_ad(dfield_check_typed(dfield));
10289
10290 821 fld = down_cast<Field_typed_array *>(mysql_table->field[f_idx]);
10291
10292
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 713 times.
821 if (old_val) {
10293
1/2
✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
108 length = fld->data_length(old_val);
10294
1/2
✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
108 ptr = fld->get_binary(old_val);
10295 } else {
10296
1/2
✓ Branch 0 taken 713 times.
✗ Branch 1 not taken.
713 length = fld->data_length();
10297
1/2
✓ Branch 0 taken 713 times.
✗ Branch 1 not taken.
713 ptr = fld->get_binary();
10298 }
10299
10300
1/2
✓ Branch 0 taken 821 times.
✗ Branch 1 not taken.
821 json_binary::Value v(json_binary::parse_binary(ptr, length));
10301
4/6
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 800 times.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 821 times.
821 ut_ad(v.type() == json_binary::Value::ARRAY ||
10302 v.type() == json_binary::Value::LITERAL_NULL);
10303
10304 ut_d(bool succ =)
10305
1/2
✓ Branch 0 taken 821 times.
✗ Branch 1 not taken.
821 innobase_store_multi_value(v, value, fld, dfield, comp, heap);
10306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 821 times.
821 ut_ad(succ);
10307 821 }
10308
10309 #ifdef WITH_WSREP
10310 /*
10311 Check if replication should be done. It should be if:
10312 a. wsrep is enabled
10313 b. exec mode is local
10314 (it is workload executor node and not replicator node)
10315 c. No consistency check enforced.
10316 d. Ensure that bin-logging is enabled.
10317 Either mysql bin-logging or emulated bin logging.
10318 */
10319 79192160 static bool wsrep_do_replication(THD *thd) {
10320
2/2
✓ Branch 0 taken 4365752 times.
✓ Branch 1 taken 3135039 times.
86692951 return wsrep_on(thd) && wsrep_thd_is_local(thd) &&
10321
3/4
✓ Branch 0 taken 7500791 times.
✓ Branch 1 taken 71691434 times.
✓ Branch 2 taken 4365760 times.
✗ Branch 3 not taken.
91058768 !wsrep_consistency_check(thd) &&
10322
2/2
✓ Branch 0 taken 4358015 times.
✓ Branch 1 taken 7737 times.
83557977 thd_binlog_format(thd) == BINLOG_FORMAT_ROW;
10323 }
10324 #endif /* WITH_WSREP */
10325
10326 /** Stores a row in an InnoDB database, to the table specified in this
10327 handle.
10328 @return error code */
10329
10330 78850095 int ha_innobase::write_row(uchar *record) /*!< in: a row in MySQL format */
10331 {
10332 dberr_t error;
10333 78850095 int error_result = 0;
10334 78850095 bool auto_inc_used = false;
10335
10336
1/2
✓ Branch 0 taken 78851552 times.
✗ Branch 1 not taken.
78850095 DBUG_TRACE;
10337
10338 #ifdef WITH_WSREP
10339
3/4
✓ Branch 0 taken 75085647 times.
✓ Branch 1 taken 3765824 times.
✓ Branch 2 taken 75085821 times.
✗ Branch 3 not taken.
78851552 DEBUG_SYNC(m_user_thd, "ha_innobase_write_row");
10340 #endif /* WITH_WSREP */
10341
10342 /* Increase the write count of handler */
10343
1/2
✓ Branch 0 taken 78851504 times.
✗ Branch 1 not taken.
78851645 ha_statistic_increment(&System_status_var::ha_write_count);
10344
10345
3/4
✓ Branch 0 taken 78851587 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13654241 times.
✓ Branch 3 taken 65197346 times.
78851504 if (m_prebuilt->table->is_intrinsic()) {
10346
1/2
✓ Branch 0 taken 13654241 times.
✗ Branch 1 not taken.
13654241 return intrinsic_table_write_row(record);
10347 }
10348
10349
1/2
✓ Branch 0 taken 65197253 times.
✗ Branch 1 not taken.
65197346 trx_t *trx = thd_to_trx(m_user_thd);
10350
10351
1/2
✓ Branch 0 taken 65196143 times.
✗ Branch 1 not taken.
65197253 TrxInInnoDB trx_in_innodb(trx);
10352
10353
8/10
✓ Branch 0 taken 65196848 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 65196636 times.
✓ Branch 3 taken 212 times.
✓ Branch 4 taken 65196866 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 65196862 times.
✓ Branch 8 taken 4 times.
✓ Branch 9 taken 65197074 times.
65196143 if (!m_prebuilt->table->is_intrinsic() && trx_in_innodb.is_aborted()) {
10354
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 innobase_rollback(ht, m_user_thd, false);
10355
10356
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd);
10357 }
10358
10359 /* Validation checks before we commence write_row operation. */
10360
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 65197043 times.
65197074 if (high_level_read_only) {
10361
2/4
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
✗ Branch 3 not taken.
31 ib_senderrf(ha_thd(), IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE);
10362 31 return HA_ERR_TABLE_READONLY;
10363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65197043 times.
65197043 } else if (m_prebuilt->trx != trx) {
10364 ib::error(ER_IB_MSG_558) << "The transaction object for the table handle is"
10365 " at "
10366 << static_cast<const void *>(m_prebuilt->trx)
10367 << ", but for the current thread it is at "
10368 << static_cast<const void *>(trx);
10369
10370 fputs("InnoDB: Dump of 200 bytes around m_prebuilt: ", stderr);
10371 ut_print_buf(stderr, ((const byte *)m_prebuilt) - 100, 200);
10372 fputs("\nInnoDB: Dump of 200 bytes around ha_data: ", stderr);
10373 ut_print_buf(stderr, ((const byte *)trx) - 100, 200);
10374 putc('\n', stderr);
10375 ut_error;
10376
3/4
✓ Branch 0 taken 65196404 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2143883 times.
✓ Branch 3 taken 63052521 times.
65197043 } else if (!trx_is_started(trx)) {
10377 2143883 ++trx->will_lock;
10378 }
10379
10380 /* Handling of Auto-Increment Columns. */
10381
3/4
✓ Branch 0 taken 14504589 times.
✓ Branch 1 taken 50691815 times.
✓ Branch 2 taken 14504622 times.
✗ Branch 3 not taken.
65196404 if (table->next_number_field && record == table->record[0]) {
10382 /* Reset the error code before calling
10383 innobase_get_auto_increment(). */
10384 14504622 m_prebuilt->autoinc_error = DB_SUCCESS;
10385
10386
1/2
✓ Branch 0 taken 14504645 times.
✗ Branch 1 not taken.
14504622 error_result = update_auto_increment();
10387
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 14504633 times.
14504645 if (error_result) {
10388 /* We don't want to mask autoinc overflow errors. */
10389
10390 /* Handle the case where the AUTOINC sub-system
10391 failed during initialization. */
10392
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (m_prebuilt->autoinc_error == DB_UNSUPPORTED) {
10393 error_result = ER_AUTOINC_READ_FAILED;
10394 /* Set the error message to report too. */
10395 my_error(ER_AUTOINC_READ_FAILED, MYF(0));
10396 goto func_exit;
10397
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 11 times.
12 } else if (m_prebuilt->autoinc_error != DB_SUCCESS) {
10398 1 error = m_prebuilt->autoinc_error;
10399 1 goto report_error;
10400 }
10401
10402 /* MySQL errors are passed straight back. */
10403 11 goto func_exit;
10404 }
10405
10406 14504633 auto_inc_used = true;
10407 }
10408
10409 /* Prepare INSERT graph that will be executed for actual INSERT
10410 (This is a one time operation) */
10411
2/2
✓ Branch 0 taken 64923808 times.
✓ Branch 1 taken 272607 times.
65196415 if (m_prebuilt->mysql_template == nullptr ||
10412
2/2
✓ Branch 0 taken 725373 times.
✓ Branch 1 taken 64198435 times.
64923808 m_prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) {
10413 /* Build the template used in converting quickly between
10414 the two database formats */
10415
10416
1/2
✓ Branch 0 taken 997825 times.
✗ Branch 1 not taken.
997980 build_template(true);
10417 }
10418
10419 #ifdef WITH_WSREP
10420 /* debug sync point has a special significance given the location
10421 where-in auto-inc value is generated but row insert action is not yet
10422 started. */
10423
3/4
✓ Branch 0 taken 61435634 times.
✓ Branch 1 taken 3760790 times.
✓ Branch 2 taken 61436511 times.
✗ Branch 3 not taken.
65196260 DEBUG_SYNC(m_user_thd, "pxc_autoinc_val_generated");
10424 #endif /* WITH_WSREP */
10425
10426
1/2
✓ Branch 0 taken 65196417 times.
✗ Branch 1 not taken.
65197301 error = innobase_srv_conc_enter_innodb(m_prebuilt);
10427
10428
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65196417 times.
65196417 if (error != DB_SUCCESS) {
10429 goto report_error;
10430 }
10431
10432 /* Execute insert graph that will result in actual insert. */
10433
1/2
✓ Branch 0 taken 65197138 times.
✗ Branch 1 not taken.
65196417 error = row_insert_for_mysql((byte *)record, m_prebuilt);
10434
10435
3/4
✓ Branch 0 taken 61436570 times.
✓ Branch 1 taken 3760828 times.
✓ Branch 2 taken 61436626 times.
✗ Branch 3 not taken.
65197138 DEBUG_SYNC(m_user_thd, "ib_after_row_insert");
10436
10437 /* Handling of errors related to auto-increment. */
10438
2/2
✓ Branch 0 taken 14504774 times.
✓ Branch 1 taken 50692680 times.
65197454 if (auto_inc_used) {
10439 ulonglong auto_inc;
10440 ulonglong col_max_value;
10441
10442 /* Note the number of rows processed for this statement, used
10443 by get_auto_increment() to determine the number of AUTO-INC
10444 values to reserve. This is only useful for a mult-value INSERT
10445 and is a statement level counter. */
10446
2/2
✓ Branch 0 taken 13069054 times.
✓ Branch 1 taken 1435720 times.
14504774 if (trx->n_autoinc_rows > 0) {
10447 13069054 --trx->n_autoinc_rows;
10448 }
10449
10450 /* We need the upper limit of the col type to check for
10451 whether we update the table autoinc counter or not. */
10452
1/2
✓ Branch 0 taken 14504774 times.
✗ Branch 1 not taken.
14504774 col_max_value = table->next_number_field->get_max_int_value();
10453
10454 /* Get the value that MySQL attempted to store in the table. */
10455
1/2
✓ Branch 0 taken 14504774 times.
✗ Branch 1 not taken.
14504774 auto_inc = table->next_number_field->val_int();
10456
10457
3/3
✓ Branch 0 taken 258 times.
✓ Branch 1 taken 14504496 times.
✓ Branch 2 taken 20 times.
14504774 switch (error) {
10458 258 case DB_DUPLICATE_KEY:
10459
10460 /* A REPLACE command and LOAD DATA INFILE REPLACE
10461 handle a duplicate key error themselves, but we
10462 must update the autoinc counter if we are performing
10463 those statements. */
10464
10465
5/6
✓ Branch 0 taken 258 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 98 times.
✓ Branch 4 taken 144 times.
✓ Branch 5 taken 10 times.
258 switch (thd_sql_command(m_user_thd)) {
10466 6 case SQLCOM_LOAD:
10467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!m_prebuilt->allow_duplicates()) {
10468 break;
10469 }
10470
10471 case SQLCOM_REPLACE:
10472 case SQLCOM_INSERT_SELECT:
10473 case SQLCOM_REPLACE_SELECT:
10474 104 goto set_max_autoinc;
10475
10476 #ifdef WITH_WSREP
10477 /* workaround for LP bug #355000, retrying the insert */
10478 144 case SQLCOM_INSERT: {
10479 const dict_index_t *err_index =
10480 144 trx_get_error_index(m_prebuilt->trx);
10481
1/30
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
144 WSREP_DEBUG(
10482 "Found duplicate value for"
10483 " table (%s) - key (%s)"
10484 " THD %u, Auto-Inc-Value: %llu"
10485 " Offset: %llu, Increment: %llu",
10486 m_prebuilt->table->name.m_name,
10487 (err_index ? err_index->name() : "UNKNOWN"),
10488 wsrep_thd_thread_id(current_thd), auto_inc,
10489 m_prebuilt->autoinc_offset, m_prebuilt->autoinc_increment);
10490
10491
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 int mysql_key = get_dup_key(HA_ERR_FOUND_DUPP_KEY);
10492
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 KEY *key = (mysql_key < 0 || mysql_key == MAX_KEY)
10493
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 ? NULL
10494 144 : &table->key_info[mysql_key];
10495
10496 char key_buff[MAX_KEY_LENGTH];
10497 144 String str(key_buff, sizeof(key_buff), system_charset_info);
10498
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 key_unpack(&str, table, key);
10499
1/26
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
144 WSREP_DEBUG("Duplicate value: %s", str.c_ptr());
10500
10501 144 break;
10502 144 }
10503 #endif /* WITH_WSREP */
10504
10505 10 default:
10506 10 break;
10507 }
10508
10509 154 break;
10510
10511 14504496 case DB_SUCCESS:
10512 /* If the actual value inserted is greater than
10513 the upper limit of the interval, then we try and
10514 update the table upper limit. Note: last_value
10515 will be 0 if get_auto_increment() was not called. */
10516
10517
2/2
✓ Branch 0 taken 1439216 times.
✓ Branch 1 taken 13065280 times.
14504496 if (auto_inc >= m_prebuilt->autoinc_last_value) {
10518 1439216 set_max_autoinc:
10519 /* This should filter out the negative
10520 values set explicitly by the user. */
10521
2/2
✓ Branch 0 taken 1439090 times.
✓ Branch 1 taken 230 times.
1439320 if (auto_inc <= col_max_value) {
10522
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1439090 times.
1439090 ut_a(m_prebuilt->autoinc_increment > 0);
10523
10524 ulonglong offset;
10525 ulonglong increment;
10526 dberr_t err;
10527
10528 #ifdef WITH_WSREP
10529 /* Applier threads which are processing ROW events and don't go
10530 through server level autoinc processing, therefore m_prebuilt
10531 autoinc values don't get properly assigned. Fetch values from
10532 server side. */
10533
9/12
✓ Branch 0 taken 1439090 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1439090 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 675928 times.
✓ Branch 5 taken 763162 times.
✓ Branch 6 taken 675928 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 655772 times.
✓ Branch 9 taken 20156 times.
✓ Branch 10 taken 655772 times.
✓ Branch 11 taken 783318 times.
1439090 if (wsrep_on(current_thd) && wsrep_thd_is_applying(m_user_thd)) {
10534
2/4
✓ Branch 0 taken 655772 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 655772 times.
✗ Branch 3 not taken.
655772 wsrep_thd_auto_increment_variables(current_thd, &offset,
10535 &increment);
10536 } else {
10537 783318 offset = m_prebuilt->autoinc_offset;
10538 783318 increment = m_prebuilt->autoinc_increment;
10539 }
10540 #else
10541 offset = m_prebuilt->autoinc_offset;
10542 increment = m_prebuilt->autoinc_increment;
10543 #endif /* WITH_WSREP */
10544
10545 #ifdef WITH_WSREP
10546 1439090 ulonglong prev_auto_inc = auto_inc;
10547 #endif /* WITH_WSREP */
10548
10549
1/2
✓ Branch 0 taken 1439090 times.
✗ Branch 1 not taken.
1439090 auto_inc = innobase_next_autoinc(auto_inc, 1, increment, offset,
10550 col_max_value);
10551
10552 #ifdef WITH_WSREP
10553
12/24
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1439088 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 2 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 2 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
1439090 WSREP_DEBUG(
10554 "Generating new auto-inc"
10555 " next-value (Current: %llu,"
10556 " New: %llu)",
10557 prev_auto_inc, auto_inc);
10558 #endif /* WITH_WSREP */
10559
10560
1/2
✓ Branch 0 taken 1439089 times.
✗ Branch 1 not taken.
1439090 err = innobase_set_max_autoinc(auto_inc);
10561
10562
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1439089 times.
1439089 if (err != DB_SUCCESS) {
10563 error = err;
10564 }
10565 }
10566 }
10567 14504599 break;
10568 20 default:
10569 20 break;
10570 }
10571 }
10572
10573
1/2
✓ Branch 0 taken 65197118 times.
✗ Branch 1 not taken.
65197453 innobase_srv_conc_exit_innodb(m_prebuilt);
10574
10575 65197119 report_error:
10576 /* Cleanup and exit. */
10577
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 65197111 times.
65197119 if (error == DB_TABLESPACE_DELETED) {
10578 8 ib_senderrf(trx->mysql_thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_DISCARDED,
10579
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 table->s->table_name.str);
10580 }
10581
10582 error_result =
10583
1/2
✓ Branch 0 taken 65197136 times.
✗ Branch 1 not taken.
65197119 convert_error_code_to_mysql(error, m_prebuilt->table->flags, m_user_thd);
10584
10585 #ifdef WITH_WSREP
10586 /* Append key
10587 a. there is no error in insert
10588 b. exec mode is local
10589 (it is workload executor node and not replicator node)
10590 c. wsrep is enabled
10591 d. No consistency check enforced.
10592 e. Ensure that bin-logging is enabled.
10593 Either mysql bin-logging or emulated bin logging.
10594 TODO: We allow replication even if binlog-format = STATEMENT.
10595 This is needed by pt-table-checksum. Now it is not a good idea
10596 to open this hook for pt-table-checksum but it exist like this for
10597 while now so to maintain compatibility we continue to provide it.
10598 With that there comes another existing dependency.
10599 Why not allow LDI operating with binlog-format = STATEMENT.
10600 There is no reason documented so will leave it as is for now. */
10601
7/8
✓ Branch 0 taken 64272389 times.
✓ Branch 1 taken 924747 times.
✓ Branch 2 taken 64272690 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 62358392 times.
✓ Branch 5 taken 1914298 times.
✓ Branch 6 taken 61496651 times.
✓ Branch 7 taken 3700791 times.
127555533 if (!error_result && (thd_sql_command(m_user_thd) != SQLCOM_CREATE_TABLE) &&
10602
3/4
✓ Branch 0 taken 62358397 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3700791 times.
✓ Branch 3 taken 58657606 times.
62358392 wsrep_do_replication(m_user_thd)) {
10603
3/4
✓ Branch 0 taken 3700791 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 3700790 times.
3700791 if (wsrep_append_keys(m_user_thd, WSREP_SERVICE_KEY_EXCLUSIVE, record,
10604 NULL)) {
10605
3/8
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1 DBUG_PRINT("wsrep", ("row key failed"));
10606 1 error_result = HA_ERR_INTERNAL_ERROR;
10607 /* If we hit error during append key then we mark for complete
10608 transaction rollback */
10609
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 thd_mark_for_rollback(m_user_thd);
10610 1 goto wsrep_error;
10611 }
10612 }
10613 61496651 wsrep_error:
10614 #endif /* WITH_WSREP */
10615
10616
2/2
✓ Branch 0 taken 65197441 times.
✓ Branch 1 taken 1 times.
65197442 if (error_result == HA_FTS_INVALID_DOCID) {
10617
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(HA_FTS_INVALID_DOCID, MYF(0));
10618 }
10619
10620 65197441 func_exit:
10621
10622
1/2
✓ Branch 0 taken 65197392 times.
✗ Branch 1 not taken.
65197453 innobase_active_small();
10623
10624 65197392 return error_result;
10625 78851668 }
10626
10627 #ifdef WITH_WSREP
10628 #include <openssl/md5.h>
10629
10630 1640278 static int wsrep_calc_row_hash(byte *digest, const uchar *row, TABLE *table,
10631 row_prebuilt_t *prebuilt, THD *thd) {
10632 Field *field;
10633 enum_field_types field_mysql_type;
10634 uint n_fields;
10635 ulint len;
10636 const byte *ptr;
10637 ulint col_type;
10638 uint i;
10639
10640
1/2
✓ Branch 0 taken 1640278 times.
✗ Branch 1 not taken.
1640278 void *ctx = wsrep_md5_init();
10641
10642 1640278 n_fields = table->s->fields;
10643
10644
2/2
✓ Branch 0 taken 1645803 times.
✓ Branch 1 taken 1640278 times.
3286081 for (i = 0; i < n_fields; i++) {
10645 1645803 byte null_byte = 0;
10646 1645803 byte true_byte = 1;
10647
10648 1645803 field = table->field[i];
10649
10650 1645803 ptr = (const byte *)row + get_field_offset(table, field);
10651
1/2
✓ Branch 0 taken 1645803 times.
✗ Branch 1 not taken.
1645803 len = field->pack_length();
10652
10653
1/2
✓ Branch 0 taken 1645803 times.
✗ Branch 1 not taken.
1645803 field_mysql_type = field->type();
10654
10655 /* Get corresponding InnoDB type */
10656 ulint unsigned_flag;
10657
1/2
✓ Branch 0 taken 1645803 times.
✗ Branch 1 not taken.
1645803 col_type = get_innobase_type_from_mysql_type(&unsigned_flag, field);
10658
10659
3/3
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 1013163 times.
✓ Branch 2 taken 632614 times.
1645803 switch (col_type) {
10660 26 case DATA_BLOB:
10661
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 ptr = row_mysql_read_blob_ref(&len, ptr, len, false, 0, 0,
10662 &prebuilt->compress_heap);
10663 26 break;
10664
10665 1013163 case DATA_VARCHAR:
10666 case DATA_BINARY:
10667 case DATA_VARMYSQL:
10668
1/2
✓ Branch 0 taken 1013163 times.
✗ Branch 1 not taken.
1013163 if (field_mysql_type == MYSQL_TYPE_VARCHAR) {
10669 /* This is a >= 5.0.3 type true VARCHAR where
10670 the real payload data length is stored in
10671 1 or 2 bytes */
10672
10673 1013163 ptr = row_mysql_read_true_varchar(
10674 &len, ptr,
10675
2/4
✓ Branch 0 taken 1013163 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1013163 times.
✗ Branch 3 not taken.
1013163 (ulint)(((Field_varstring *)field)->get_length_bytes()));
10676 }
10677
10678 1013163 break;
10679 632614 default:
10680 632614 break;
10681 }
10682
10683
3/4
✓ Branch 0 taken 1645803 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 126 times.
✓ Branch 3 taken 1645677 times.
1645803 if (field->is_null_in_record(row)) {
10684
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
126 wsrep_md5_update(ctx, (char *)&null_byte, 1);
10685 } else {
10686
1/2
✓ Branch 0 taken 1645677 times.
✗ Branch 1 not taken.
1645677 wsrep_md5_update(ctx, (char *)&true_byte, 1);
10687
1/2
✓ Branch 0 taken 1645677 times.
✗ Branch 1 not taken.
1645677 wsrep_md5_update(ctx, (char *)ptr, len);
10688 }
10689 }
10690
1/2
✓ Branch 0 taken 1640278 times.
✗ Branch 1 not taken.
1640278 wsrep_compute_md5_hash(digest, ctx);
10691 1640278 return (0);
10692 }
10693 #endif /* WITH_WSREP */
10694
10695 /** Fill the update vector's "old_vrow" field for those non-updated,
10696 but indexed columns. Such columns could stil present in the virtual
10697 index rec fields even if they are not updated (some other fields updated),
10698 so needs to be logged.
10699 @param[in] prebuilt InnoDB prebuilt struct
10700 @param[in,out] vfield field to filled
10701 @param[in] o_len actual column length
10702 @param[in] old_mysql_row_col MySQL old field ptr
10703 @param[in] col_pack_len MySQL field col length
10704 @param[in,out] buf buffer for a converted integer value
10705 @return used buffer ptr from row_mysql_store_col_in_innobase_format() */
10706 1225 static byte *innodb_fill_old_vcol_val(row_prebuilt_t *prebuilt,
10707 dfield_t *vfield, ulint o_len,
10708 const byte *old_mysql_row_col,
10709 ulint col_pack_len, byte *buf) {
10710
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1225 times.
1225 ut_ad(dfield_check_typed(vfield));
10711
10712
2/2
✓ Branch 0 taken 1209 times.
✓ Branch 1 taken 16 times.
1225 if (o_len != UNIV_SQL_NULL) {
10713 1209 buf = row_mysql_store_col_in_innobase_format(
10714 vfield, buf, true, old_mysql_row_col, col_pack_len,
10715 1209 dict_table_is_comp(prebuilt->table), false, nullptr, 0, nullptr);
10716 } else {
10717 16 dfield_set_null(vfield);
10718 }
10719
10720 1225 return (buf);
10721 }
10722
10723 /** Parse out multi-values from both old and new MySQL records,
10724 at the meantime, calculate the difference between two records.
10725 @param[in] mysql_table MySQL table structure
10726 @param[in] field_idx field index of the multi-value column
10727 @param[in,out] old_field field structure to store the parsed old value
10728 @param[in,out] new_field field structure to store the parsed new value
10729 @param[in] old_value old value to parse
10730 @param[in] comp true if InnoDB table uses compact row format
10731 @param[in,out] heap memory heap */
10732 85 static void innobase_get_multi_value_and_diff(
10733 const TABLE *mysql_table, ulint field_idx, dfield_t *old_field,
10734 dfield_t *new_field, uint old_value, ulint comp, mem_heap_t *heap) {
10735 Field_typed_array *fld;
10736 85 const char *old_ptr = nullptr;
10737 85 const char *new_ptr = nullptr;
10738 uint old_len;
10739 uint new_len;
10740
10741 85 fld = down_cast<Field_typed_array *>(mysql_table->field[field_idx]);
10742
10743
1/2
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
85 old_ptr = fld->get_binary(old_value);
10744
1/2
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
85 old_len = fld->get_length(old_value);
10745
1/2
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
85 new_ptr = fld->get_binary();
10746
1/2
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
85 new_len = fld->get_length();
10747
10748
1/2
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
85 json_binary::Value old_v(json_binary::parse_binary(old_ptr, old_len));
10749
1/2
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
85 json_binary::Value new_v(json_binary::parse_binary(new_ptr, new_len));
10750
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
85 ut_ad(old_v.type() == json_binary::Value::ARRAY);
10751
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
85 ut_ad(new_v.type() == json_binary::Value::ARRAY);
10752
10753 ut_d(bool succ1 =)
10754
1/2
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
85 innobase_store_multi_value(old_v, nullptr, fld, old_field, comp, heap);
10755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
85 ut_ad(succ1);
10756 ut_d(bool succ2 =)
10757
1/2
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
85 innobase_store_multi_value(new_v, nullptr, fld, new_field, comp, heap);
10758
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
85 ut_ad(succ2);
10759
10760
2/4
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 85 times.
85 ut_ad(!dfield_is_null(old_field));
10761
2/4
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 85 times.
85 ut_ad(!dfield_is_null(new_field));
10762 /* If no indexed value, then no need to get the difference */
10763
1/2
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
85 if (old_field->len == UNIV_NO_INDEX_VALUE ||
10764
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
85 new_field->len == UNIV_NO_INDEX_VALUE) {
10765 return;
10766 }
10767
10768 /* Now old_field and new_field are having both multi-value data, in the
10769 same sequence with data in old_v and new_v, which are also sorted in
10770 ascending order. */
10771
10772 85 uint old_counter = 0;
10773 85 uint new_counter = 0;
10774 85 multi_value_data *old_mv = static_cast<multi_value_data *>(old_field->data);
10775 85 multi_value_data *new_mv = static_cast<multi_value_data *>(new_field->data);
10776
10777
1/2
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
85 old_mv->alloc_bitset(heap);
10778
1/2
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
85 new_mv->alloc_bitset(heap);
10779
10780
6/6
✓ Branch 0 taken 294 times.
✓ Branch 1 taken 76 times.
✓ Branch 2 taken 285 times.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 285 times.
✓ Branch 5 taken 85 times.
664 while (old_counter < old_v.element_count() &&
10781 294 new_counter < new_v.element_count()) {
10782
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 285 times.
285 ut_ad(old_counter < old_mv->num_v);
10783
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 285 times.
285 ut_ad(new_counter < new_mv->num_v);
10784
10785
3/6
✓ Branch 0 taken 285 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 285 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 285 times.
✗ Branch 5 not taken.
285 int res = old_v.element(old_counter).eq(new_v.element(new_counter));
10786
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 203 times.
285 if (res == 0) {
10787
1/2
✓ Branch 0 taken 82 times.
✗ Branch 1 not taken.
82 old_mv->bitset->set(old_counter++, false);
10788
1/2
✓ Branch 0 taken 82 times.
✗ Branch 1 not taken.
82 new_mv->bitset->set(new_counter++, false);
10789
2/2
✓ Branch 0 taken 168 times.
✓ Branch 1 taken 35 times.
203 } else if (res < 0) {
10790 168 ++old_counter;
10791 } else {
10792 35 ++new_counter;
10793 }
10794 }
10795 }
10796
10797 /** Checks which fields have changed in a row and stores information
10798 of them to an update vector.
10799 @return DB_SUCCESS or error code */
10800 14643831 static dberr_t calc_row_difference(
10801 upd_t *uvect, /*!< in/out: update vector */
10802 const uchar *old_row, /*!< in: old row in MySQL format */
10803 uchar *new_row, /*!< in: new row in MySQL format */
10804 TABLE *table, /*!< in: table in MySQL data
10805 dictionary */
10806 uchar *upd_buff, /*!< in: buffer to use */
10807 ulint buff_len, /*!< in: buffer length */
10808 row_prebuilt_t *prebuilt, /*!< in: InnoDB prebuilt struct */
10809 THD *thd) /*!< in: user thread */
10810 {
10811 14643831 uchar *original_upd_buff = upd_buff;
10812 Field *field;
10813 enum_field_types field_mysql_type;
10814 uint n_fields;
10815 ulint o_len;
10816 ulint n_len;
10817 ulint col_pack_len;
10818 const byte *new_mysql_row_col;
10819 const byte *old_mysql_row_col;
10820 const byte *o_ptr;
10821 const byte *n_ptr;
10822 byte *buf;
10823 upd_field_t *ufield;
10824 ulint col_type;
10825 14643831 ulint n_changed = 0;
10826 14643831 dfield_t dfield;
10827 dict_index_t *clust_index;
10828 uint i;
10829 14643846 bool changes_fts_column = false;
10830 14643846 bool changes_fts_doc_col = false;
10831
1/2
✓ Branch 0 taken 14643849 times.
✗ Branch 1 not taken.
14643846 trx_t *trx = thd_to_trx(thd);
10832 14643849 doc_id_t doc_id = FTS_NULL_DOC_ID;
10833 14643849 ulint comp = 0;
10834 14643849 ulint num_v = 0;
10835
10836
5/8
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 14643845 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 14643851 times.
14643849 ut_ad(!srv_read_only_mode || prebuilt->table->is_intrinsic());
10837
10838
1/2
✓ Branch 0 taken 14643838 times.
✗ Branch 1 not taken.
14643851 comp = dict_table_is_comp(prebuilt->table);
10839
10840 14643838 n_fields = table->s->fields;
10841
1/2
✓ Branch 0 taken 14643845 times.
✗ Branch 1 not taken.
14643838 clust_index = prebuilt->table->first_index();
10842
10843 /* We use upd_buff to convert changed fields */
10844 14643845 buf = (byte *)upd_buff;
10845
10846
2/2
✓ Branch 0 taken 147578907 times.
✓ Branch 1 taken 14643871 times.
162222778 for (i = 0; i < n_fields; i++) {
10847 147578907 dfield.reset();
10848
10849 147578961 field = table->field[i];
10850
4/4
✓ Branch 0 taken 316102 times.
✓ Branch 1 taken 147262859 times.
✓ Branch 2 taken 166284 times.
✓ Branch 3 taken 149818 times.
147578961 bool is_virtual = innobase_is_v_fld(field);
10851
1/2
✓ Branch 0 taken 147578942 times.
✗ Branch 1 not taken.
147578961 bool is_multi_value = innobase_is_multi_value_fld(field);
10852 dict_col_t *col;
10853
10854
2/2
✓ Branch 0 taken 166284 times.
✓ Branch 1 taken 147412658 times.
147578942 if (is_virtual) {
10855 166284 col = &prebuilt->table->v_cols[num_v].m_col;
10856 } else {
10857 147412658 col = &prebuilt->table->cols[i - num_v];
10858 }
10859
10860 147578942 o_ptr = (const byte *)old_row + get_field_offset(table, field);
10861 147578945 n_ptr = (const byte *)new_row + get_field_offset(table, field);
10862
10863 /* Use new_mysql_row_col and col_pack_len save the values */
10864
10865 147578883 new_mysql_row_col = n_ptr;
10866 147578883 old_mysql_row_col = o_ptr;
10867
1/2
✓ Branch 0 taken 147578843 times.
✗ Branch 1 not taken.
147578883 col_pack_len = field->pack_length();
10868
10869 147578843 o_len = col_pack_len;
10870 147578843 n_len = col_pack_len;
10871
10872 /* We use o_ptr and n_ptr to dig up the actual data for
10873 comparison. */
10874
10875
1/2
✓ Branch 0 taken 147578863 times.
✗ Branch 1 not taken.
147578843 field_mysql_type = field->type();
10876
10877 147578863 col_type = col->mtype;
10878
10879 /* Reset the type to BLOB for multi-value field, since server may
10880 keep it as non-BLOB one. */
10881
2/2
✓ Branch 0 taken 201 times.
✓ Branch 1 taken 147578662 times.
147578863 if (is_multi_value) {
10882 201 col_type = DATA_BLOB;
10883 }
10884
10885
3/3
✓ Branch 0 taken 30520499 times.
✓ Branch 1 taken 18926659 times.
✓ Branch 2 taken 98131705 times.
147578863 switch (col_type) {
10886 30520499 case DATA_BLOB:
10887 case DATA_POINT:
10888 case DATA_VAR_POINT:
10889 case DATA_GEOMETRY:
10890 /* Do not compress blob column while comparing */
10891
1/2
✓ Branch 0 taken 30520511 times.
✗ Branch 1 not taken.
30520499 o_ptr = row_mysql_read_blob_ref(&o_len, o_ptr, o_len, false, nullptr, 0,
10892 &prebuilt->compress_heap);
10893
1/2
✓ Branch 0 taken 30520506 times.
✗ Branch 1 not taken.
30520511 n_ptr = row_mysql_read_blob_ref(&n_len, n_ptr, n_len, false, nullptr, 0,
10894 &prebuilt->compress_heap);
10895
10896 30520506 break;
10897
10898 18926659 case DATA_VARCHAR:
10899 case DATA_BINARY:
10900 case DATA_VARMYSQL:
10901
1/2
✓ Branch 0 taken 18926661 times.
✗ Branch 1 not taken.
18926659 if (field_mysql_type == MYSQL_TYPE_VARCHAR) {
10902 /* This is a >= 5.0.3 type true VARCHAR where
10903 the real payload data length is stored in
10904 1 or 2 bytes */
10905
10906 37853307 o_ptr = row_mysql_read_true_varchar(&o_len, o_ptr,
10907
2/4
✓ Branch 0 taken 18926654 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18926653 times.
✗ Branch 3 not taken.
18926661 (ulint)field->get_length_bytes());
10908
10909 18926664 n_ptr = row_mysql_read_true_varchar(&n_len, n_ptr,
10910
2/4
✓ Branch 0 taken 18926659 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18926664 times.
✗ Branch 3 not taken.
18926653 (ulint)field->get_length_bytes());
10911 }
10912
10913 18926662 break;
10914 147578873 default:;
10915 }
10916
10917
6/6
✓ Branch 0 taken 25419321 times.
✓ Branch 1 taken 122159552 times.
✓ Branch 2 taken 305 times.
✓ Branch 3 taken 25419016 times.
✓ Branch 4 taken 305 times.
✓ Branch 5 taken 147578568 times.
147579178 if (field_mysql_type == MYSQL_TYPE_LONGLONG && prebuilt->table->fts &&
10918
2/4
✓ Branch 0 taken 305 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 305 times.
✗ Branch 3 not taken.
305 innobase_strcasecmp(field->field_name, FTS_DOC_ID_COL_NAME) == 0) {
10919
1/2
✓ Branch 0 taken 305 times.
✗ Branch 1 not taken.
305 doc_id = (doc_id_t)mach_read_from_n_little_endian(n_ptr, 8);
10920
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 305 times.
305 if (doc_id == 0) {
10921 return (DB_FTS_INVALID_DOCID);
10922 }
10923 }
10924
10925
2/2
✓ Branch 0 taken 75611001 times.
✓ Branch 1 taken 71967929 times.
147578873 if (field->is_nullable()) {
10926
3/4
✓ Branch 0 taken 75610995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 35965207 times.
✓ Branch 3 taken 39645788 times.
75611001 if (field->is_null_in_record(old_row)) {
10927 35965207 o_len = UNIV_SQL_NULL;
10928 }
10929
10930
3/4
✓ Branch 0 taken 75610985 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 34548052 times.
✓ Branch 3 taken 41062933 times.
75610995 if (field->is_null_in_record(new_row)) {
10931 34548052 n_len = UNIV_SQL_NULL;
10932 }
10933 }
10934
10935 #ifdef UNIV_DEBUG
10936 147578914 bool online_ord_part = false;
10937 #endif
10938
10939
2/2
✓ Branch 0 taken 166284 times.
✓ Branch 1 taken 147412630 times.
147578914 if (is_virtual) {
10940 /* If the virtual column is not indexed,
10941 we shall ignore it for update */
10942
2/2
✓ Branch 0 taken 159692 times.
✓ Branch 1 taken 6592 times.
166284 if (!col->ord_part) {
10943 /* Check whether there is a table-rebuilding
10944 online ALTER TABLE in progress, and this
10945 virtual column could be newly indexed, thus
10946 it will be materialized. Then we will have
10947 to log its update.
10948 Note, we do not support online dropping virtual
10949 column while adding new index, nor with
10950 online alter column order while adding index,
10951 so the virtual column sequence must not change
10952 if it is online operation */
10953
5/6
✓ Branch 0 taken 159692 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 159687 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 159691 times.
159697 if (dict_index_is_online_ddl(clust_index) &&
10954
3/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 4 times.
5 row_log_col_is_indexed(clust_index, num_v)) {
10955 #ifdef UNIV_DEBUG
10956 1 online_ord_part = true;
10957 #endif
10958 } else {
10959 159691 num_v++;
10960 159691 continue;
10961 }
10962 }
10963
10964
2/2
✓ Branch 0 taken 216 times.
✓ Branch 1 taken 6377 times.
6593 if (!uvect->old_vrow) {
10965 216 uvect->old_vrow =
10966
1/2
✓ Branch 0 taken 216 times.
✗ Branch 1 not taken.
216 dtuple_create_with_vcol(uvect->heap, 0, prebuilt->table->n_v_cols);
10967
2/2
✓ Branch 0 taken 364 times.
✓ Branch 1 taken 216 times.
580 for (uint j = 0; j < prebuilt->table->n_v_cols; j++) {
10968
1/2
✓ Branch 0 taken 364 times.
✗ Branch 1 not taken.
364 dfield_t *field = dtuple_get_nth_v_field(uvect->old_vrow, j);
10969 /* In case a multi-value field checking read uninitialized value */
10970
1/2
✓ Branch 0 taken 364 times.
✗ Branch 1 not taken.
364 dfield_get_type(field)->prtype = 0;
10971
1/2
✓ Branch 0 taken 364 times.
✗ Branch 1 not taken.
364 dfield_set_len(field, UNIV_SQL_NULL);
10972 }
10973 }
10974
10975
2/2
✓ Branch 0 taken 5785 times.
✓ Branch 1 taken 808 times.
6593 ulint max_field_len = DICT_MAX_FIELD_LEN_BY_FORMAT(prebuilt->table);
10976
10977 /* for virtual columns, we only materialize
10978 its index, and index field length would not
10979 exceed max_field_len. So continue if the
10980 first max_field_len bytes are matched up */
10981
4/4
✓ Branch 0 taken 6540 times.
✓ Branch 1 taken 53 times.
✓ Branch 2 taken 6509 times.
✓ Branch 3 taken 31 times.
6593 if (o_len != UNIV_SQL_NULL && n_len != UNIV_SQL_NULL &&
10982
3/4
✓ Branch 0 taken 1608 times.
✓ Branch 1 taken 4901 times.
✓ Branch 2 taken 1608 times.
✗ Branch 3 not taken.
6509 o_len >= max_field_len && n_len >= max_field_len &&
10983
2/2
✓ Branch 0 taken 606 times.
✓ Branch 1 taken 1002 times.
1608 memcmp(o_ptr, n_ptr, max_field_len) == 0) {
10984
1/2
✓ Branch 0 taken 606 times.
✗ Branch 1 not taken.
606 dfield_t *vfield = dtuple_get_nth_v_field(uvect->old_vrow, num_v);
10985
2/4
✓ Branch 0 taken 606 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 606 times.
✗ Branch 3 not taken.
606 col->copy_type(dfield_get_type(vfield));
10986
10987
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 606 times.
606 if (is_multi_value) {
10988 innobase_get_multi_value(prebuilt->m_mysql_table, i, vfield, nullptr,
10989 static_cast<uint>(old_row - new_row), comp,
10990 uvect->per_stmt_heap);
10991 } else {
10992
1/2
✓ Branch 0 taken 606 times.
✗ Branch 1 not taken.
606 buf = innodb_fill_old_vcol_val(prebuilt, vfield, o_len,
10993 old_mysql_row_col, col_pack_len, buf);
10994 }
10995 606 num_v++;
10996 606 continue;
10997 606 }
10998 }
10999
11000
6/6
✓ Branch 0 taken 145327803 times.
✓ Branch 1 taken 2090814 times.
✓ Branch 2 taken 110933312 times.
✓ Branch 3 taken 34394491 times.
✓ Branch 4 taken 106484623 times.
✓ Branch 5 taken 4448689 times.
147418617 if (o_len != n_len || (o_len != UNIV_SQL_NULL && o_len != 0 &&
11001
2/2
✓ Branch 0 taken 7170946 times.
✓ Branch 1 taken 99313677 times.
106484623 0 != memcmp(o_ptr, n_ptr, o_len))) {
11002 /* The field has changed */
11003 9261760 bool multi_value_calc_by_diff = false;
11004 9261760 dfield_t old_field, new_field;
11005
11006 9261790 ufield = uvect->fields + n_changed;
11007
11008 9261790 const auto old_old_v_val = ufield->old_v_val;
11009
11010 UNIV_MEM_INVALID(ufield, sizeof *ufield);
11011
11012 /* Let us use a dummy dfield to make the conversion
11013 from the MySQL column format to the InnoDB format */
11014
11015 /* If the length of new geometry object is 0, means
11016 this object is invalid geometry object, we need
11017 to block it. */
11018
5/8
✓ Branch 0 taken 3248 times.
✓ Branch 1 taken 9258547 times.
✓ Branch 2 taken 3248 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3248 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 9261795 times.
9261790 if (DATA_GEOMETRY_MTYPE(col_type) && o_len != 0 && n_len == 0) {
11019 return (DB_CANT_CREATE_GEOMETRY_OBJECT);
11020 }
11021
11022
6/6
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 9261683 times.
✓ Branch 2 taken 93 times.
✓ Branch 3 taken 19 times.
✓ Branch 4 taken 85 times.
✓ Branch 5 taken 9261710 times.
9261888 if (is_multi_value && n_len != UNIV_SQL_NULL &&
11023
3/4
✓ Branch 0 taken 93 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 85 times.
✓ Branch 3 taken 8 times.
93 !field->is_null_in_record(old_row)) {
11024 /* Multi-value field and both old and new are not NULL,
11025 parse the value separately and also calculate the difference */
11026
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
85 ut_ad(is_virtual);
11027
11028
2/4
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 85 times.
✗ Branch 3 not taken.
85 col->copy_type(dfield_get_type(&old_field));
11029
2/4
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 85 times.
✗ Branch 3 not taken.
85 col->copy_type(dfield_get_type(&new_field));
11030
11031 85 innobase_get_multi_value_and_diff(
11032 85 prebuilt->m_mysql_table, i, &old_field, &new_field,
11033
1/2
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
85 static_cast<uint>(old_row - new_row), comp, uvect->per_stmt_heap);
11034
11035 85 multi_value_calc_by_diff = true;
11036 }
11037
11038
2/2
✓ Branch 0 taken 9239333 times.
✓ Branch 1 taken 22462 times.
9261795 if (n_len != UNIV_SQL_NULL) {
11039
2/4
✓ Branch 0 taken 9239324 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9239322 times.
✗ Branch 3 not taken.
9239333 col->copy_type(dfield_get_type(&dfield));
11040
11041
4/4
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 9239229 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 85 times.
9239322 if (is_multi_value && !multi_value_calc_by_diff) {
11042
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 innobase_get_multi_value(prebuilt->m_mysql_table, i, &dfield, nullptr,
11043 0, comp, uvect->per_stmt_heap);
11044 } else {
11045
1/2
✓ Branch 0 taken 9239302 times.
✗ Branch 1 not taken.
9239311 buf = row_mysql_store_col_in_innobase_format(
11046 &dfield, (byte *)buf, true, new_mysql_row_col, col_pack_len, comp,
11047 9239314 field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED,
11048 9239314 reinterpret_cast<const byte *>(field->zip_dict_data.str),
11049 field->zip_dict_data.length, &prebuilt->compress_heap);
11050 }
11051
11052
2/2
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 9239225 times.
9239310 if (multi_value_calc_by_diff) {
11053 85 dfield_copy(&ufield->new_val, &new_field);
11054 } else {
11055 9239225 dfield_copy(&ufield->new_val, &dfield);
11056 }
11057 } else {
11058
2/4
✓ Branch 0 taken 22456 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22456 times.
✗ Branch 3 not taken.
22462 col->copy_type(dfield_get_type(&ufield->new_val));
11059
1/2
✓ Branch 0 taken 22453 times.
✗ Branch 1 not taken.
22456 dfield_set_null(&ufield->new_val);
11060 }
11061
11062 9261757 ufield->exp = nullptr;
11063 9261757 ufield->orig_len = 0;
11064 9261757 ufield->mysql_field = field;
11065
11066
2/2
✓ Branch 0 taken 5279 times.
✓ Branch 1 taken 9256478 times.
9261757 if (is_virtual) {
11067
1/2
✓ Branch 0 taken 5279 times.
✗ Branch 1 not taken.
5279 dfield_t *vfield = dtuple_get_nth_v_field(uvect->old_vrow, num_v);
11068 5279 upd_fld_set_virtual_col(ufield);
11069 /* Set ufield->field_no to store the position of virtual column. */
11070 5279 ufield->field_no = num_v;
11071
11072
4/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5278 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 5279 times.
5279 ut_ad(col->ord_part || online_ord_part);
11073
2/2
✓ Branch 0 taken 154 times.
✓ Branch 1 taken 5125 times.
5279 if (old_old_v_val == nullptr) {
11074 154 ufield->old_v_val = static_cast<dfield_t *>(
11075
1/2
✓ Branch 0 taken 154 times.
✗ Branch 1 not taken.
154 mem_heap_alloc(uvect->heap, sizeof *ufield->old_v_val));
11076 } else {
11077 UNIV_MEM_VALID(ufield, sizeof *ufield);
11078 5125 ufield->old_v_val->reset();
11079 }
11080
11081
3/4
✓ Branch 0 taken 5279 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5263 times.
✓ Branch 3 taken 16 times.
5279 if (!field->is_null_in_record(old_row)) {
11082
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 5232 times.
5263 if (n_len == UNIV_SQL_NULL) {
11083
2/4
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
✗ Branch 3 not taken.
31 col->copy_type(dfield_get_type(&dfield));
11084 }
11085
11086
4/4
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 5159 times.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 85 times.
5263 if (is_multi_value && !multi_value_calc_by_diff) {
11087 19 innobase_get_multi_value(prebuilt->m_mysql_table, i, &dfield,
11088 nullptr,
11089
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 static_cast<uint>(old_row - new_row), comp,
11090 uvect->per_stmt_heap);
11091 } else {
11092
1/2
✓ Branch 0 taken 5244 times.
✗ Branch 1 not taken.
5244 buf = row_mysql_store_col_in_innobase_format(
11093 &dfield, (byte *)buf, true, old_mysql_row_col, col_pack_len,
11094 5244 comp, field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED,
11095 5244 reinterpret_cast<const byte *>(field->zip_dict_data.str),
11096 field->zip_dict_data.length, &prebuilt->compress_heap);
11097 }
11098
11099
2/2
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 5178 times.
5263 if (multi_value_calc_by_diff) {
11100 85 dfield_copy(ufield->old_v_val, &old_field);
11101 85 dfield_copy(vfield, &old_field);
11102 } else {
11103 5178 dfield_copy(ufield->old_v_val, &dfield);
11104 5178 dfield_copy(vfield, &dfield);
11105 }
11106 } else {
11107
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 col->copy_type(dfield_get_type(ufield->old_v_val));
11108
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 dfield_set_null(ufield->old_v_val);
11109
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 dfield_set_null(vfield);
11110 }
11111 5279 num_v++;
11112 } else {
11113 /* Set ufield->field_no to store the position of column in
11114 clustered index. */
11115 18512973 ufield->field_no = dict_col_get_clust_pos(
11116
1/2
✓ Branch 0 taken 9256495 times.
✗ Branch 1 not taken.
9256478 &prebuilt->table->cols[i - num_v], clust_index);
11117 #ifdef UNIV_DEBUG
11118
2/2
✓ Branch 0 taken 690 times.
✓ Branch 1 taken 9255810 times.
9256495 if (clust_index->has_row_versions()) {
11119 690 dict_col_t *col = &prebuilt->table->cols[i - num_v];
11120 690 ufield->field_phy_pos = col->get_col_phy_pos();
11121 }
11122 #endif
11123 9256500 ufield->old_v_val = nullptr;
11124 }
11125 9261779 n_changed++;
11126
11127 /* If an FTS indexed column was changed by this
11128 UPDATE then we need to inform the FTS sub-system.
11129
11130 NOTE: Currently we re-index all FTS indexed columns
11131 even if only a subset of the FTS indexed columns
11132 have been updated. That is the reason we are
11133 checking only once here. Later we will need to
11134 note which columns have been updated and do
11135 selective processing. */
11136
3/4
✓ Branch 0 taken 14998 times.
✓ Branch 1 taken 9246781 times.
✓ Branch 2 taken 14998 times.
✗ Branch 3 not taken.
9261779 if (prebuilt->table->fts != nullptr && !is_virtual) {
11137 ulint offset;
11138 dict_table_t *innodb_table;
11139
11140 14998 innodb_table = prebuilt->table;
11141
11142
2/2
✓ Branch 0 taken 14684 times.
✓ Branch 1 taken 314 times.
14998 if (!changes_fts_column) {
11143
1/2
✓ Branch 0 taken 14684 times.
✗ Branch 1 not taken.
14684 offset = row_upd_changes_fts_column(innodb_table, ufield);
11144
11145
2/2
✓ Branch 0 taken 14366 times.
✓ Branch 1 taken 318 times.
14684 if (offset != ULINT_UNDEFINED) {
11146 14366 changes_fts_column = true;
11147 }
11148 }
11149
11150
2/2
✓ Branch 0 taken 14393 times.
✓ Branch 1 taken 605 times.
14998 if (!changes_fts_doc_col) {
11151
1/2
✓ Branch 0 taken 14393 times.
✗ Branch 1 not taken.
14393 changes_fts_doc_col = row_upd_changes_doc_id(innodb_table, ufield);
11152 }
11153 }
11154
2/2
✓ Branch 0 taken 708 times.
✓ Branch 1 taken 138156149 times.
147418636 } else if (is_virtual) {
11155
1/2
✓ Branch 0 taken 708 times.
✗ Branch 1 not taken.
708 dfield_t *vfield = dtuple_get_nth_v_field(uvect->old_vrow, num_v);
11156
2/4
✓ Branch 0 taken 708 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 708 times.
✗ Branch 3 not taken.
708 col->copy_type(dfield_get_type(vfield));
11157
11158
2/2
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 619 times.
708 if (is_multi_value) {
11159 89 innobase_get_multi_value(prebuilt->m_mysql_table, i, vfield, nullptr,
11160
1/2
✓ Branch 0 taken 89 times.
✗ Branch 1 not taken.
89 static_cast<uint>(old_row - new_row), comp,
11161 uvect->per_stmt_heap);
11162 } else {
11163
1/2
✓ Branch 0 taken 619 times.
✗ Branch 1 not taken.
619 buf = innodb_fill_old_vcol_val(prebuilt, vfield, o_len,
11164 old_mysql_row_col, col_pack_len, buf);
11165 }
11166
11167
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 708 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 708 times.
708 ut_ad(col->ord_part || online_ord_part);
11168 708 num_v++;
11169 }
11170 }
11171
11172 /* If the update changes a column with an FTS index on it, we
11173 then add an update column node with a new document id to the
11174 other changes. We piggy back our changes on the normal UPDATE
11175 to reduce processing and IO overhead. */
11176
2/2
✓ Branch 0 taken 14629464 times.
✓ Branch 1 taken 14407 times.
14643871 if (!prebuilt->table->fts) {
11177 14629464 trx->fts_next_doc_id = 0;
11178
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 14394 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
14407 } else if (changes_fts_column || changes_fts_doc_col) {
11179 14394 dict_table_t *innodb_table = prebuilt->table;
11180
11181 14394 ufield = uvect->fields + n_changed;
11182
11183
2/2
✓ Branch 0 taken 305 times.
✓ Branch 1 taken 14061 times.
14394 if (!DICT_TF2_FLAG_IS_SET(innodb_table, DICT_TF2_FTS_HAS_DOC_ID)) {
11184 /* If Doc ID is managed by user, and if any
11185 FTS indexed column has been updated, its corresponding
11186 Doc ID must also be updated. Otherwise, return
11187 error */
11188
3/4
✓ Branch 0 taken 305 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 304 times.
305 if (changes_fts_column && !changes_fts_doc_col) {
11189
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
2 ib::warn(ER_IB_MSG_559) << "A new Doc ID must be supplied"
11190
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 " while updating FTS indexed columns.";
11191 1 return (DB_FTS_INVALID_DOCID);
11192 }
11193
11194 /* Doc ID must monotonically increase */
11195
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 304 times.
304 ut_ad(innodb_table->fts->cache);
11196
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 303 times.
304 if (doc_id < prebuilt->table->fts->cache->next_doc_id) {
11197
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 ib::warn(ER_IB_MSG_560) << "FTS Doc ID must be larger than "
11198
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
2 << innodb_table->fts->cache->next_doc_id - 1
11199
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 << " for table " << innodb_table->name;
11200
11201 1 return (DB_FTS_INVALID_DOCID);
11202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 303 times.
303 } else if ((doc_id - prebuilt->table->fts->cache->next_doc_id) >=
11203 FTS_DOC_ID_MAX_STEP) {
11204 ib::warn(ER_IB_MSG_561)
11205 << "Doc ID " << doc_id
11206 << " is too"
11207 " big. Its difference with largest"
11208 " Doc ID used "
11209 << prebuilt->table->fts->cache->next_doc_id - 1
11210 << " cannot exceed or equal to " << FTS_DOC_ID_MAX_STEP;
11211 }
11212
11213 303 trx->fts_next_doc_id = doc_id;
11214 } else {
11215 /* If the Doc ID is a hidden column, it can't be
11216 changed by user */
11217
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14061 times.
14061 ut_ad(!changes_fts_doc_col);
11218
11219 /* Doc ID column is hidden, a new Doc ID will be
11220 generated by following fts_update_doc_id() call */
11221 14061 trx->fts_next_doc_id = 0;
11222 }
11223
11224
1/2
✓ Branch 0 taken 14364 times.
✗ Branch 1 not taken.
14364 fts_update_doc_id(innodb_table, ufield, &trx->fts_next_doc_id);
11225
11226 14364 ++n_changed;
11227 14364 } else {
11228 /* We have a Doc ID column, but none of FTS indexed
11229 columns are touched, nor the Doc ID column, so set
11230 fts_next_doc_id to UINT64_UNDEFINED, which means do not
11231 update the Doc ID column */
11232 13 trx->fts_next_doc_id = UINT64_UNDEFINED;
11233 }
11234
11235 14643841 uvect->n_fields = n_changed;
11236 14643841 uvect->info_bits = 0;
11237
11238
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14643824 times.
14643841 ut_a(buf <= (byte *)original_upd_buff + buff_len);
11239
11240
3/4
✓ Branch 0 taken 14643846 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 14643843 times.
14643824 ut_ad(uvect->validate());
11241 14643843 return (DB_SUCCESS);
11242 }
11243
11244 /**
11245 Updates a row given as a parameter to a new value. Note that we are given
11246 whole rows, not just the fields which are updated: this incurs some
11247 overhead for CPU when we check which fields are actually updated.
11248 TODO: currently InnoDB does not prevent the 'Halloween problem':
11249 in a searched update a single row can get updated several times
11250 if its index columns are updated!
11251 @param[in] old_row Old row contents in MySQL format
11252 @param[out] new_row Updated row contents in MySQL format
11253 @return error number or 0 */
11254
11255 14643832 int ha_innobase::update_row(const uchar *old_row, uchar *new_row) {
11256 int err;
11257
11258 dberr_t error;
11259
1/2
✓ Branch 0 taken 14643850 times.
✗ Branch 1 not taken.
14643832 trx_t *trx = thd_to_trx(m_user_thd);
11260 14643850 uint64_t new_counter = 0;
11261
11262
1/2
✓ Branch 0 taken 14643857 times.
✗ Branch 1 not taken.
14643850 DBUG_TRACE;
11263
11264 #ifdef WITH_WSREP
11265
3/4
✓ Branch 0 taken 14148087 times.
✓ Branch 1 taken 495770 times.
✓ Branch 2 taken 14148078 times.
✗ Branch 3 not taken.
14643857 DEBUG_SYNC(m_user_thd, "ha_innobase_update_row");
11266 #endif /* WITH_WSREP */
11267
11268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14643854 times.
14643848 ut_a(m_prebuilt->trx == trx);
11269
11270
7/8
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 14643845 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 5 times.
✓ Branch 7 taken 14643849 times.
14643854 if (high_level_read_only && !m_prebuilt->table->is_intrinsic()) {
11271
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 ib_senderrf(ha_thd(), IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE);
11272 5 return HA_ERR_TABLE_READONLY;
11273
2/4
✓ Branch 0 taken 14643839 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 14643839 times.
14643849 } else if (!trx_is_started(trx)) {
11274 ++trx->will_lock;
11275 }
11276
11277
2/2
✓ Branch 0 taken 208129 times.
✓ Branch 1 taken 14435710 times.
14643839 if (m_upd_buf == nullptr) {
11278
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 208129 times.
208129 ut_ad(m_upd_buf_size == 0);
11279
11280 /* Create a buffer for packing the fields of a record. Why
11281 table->reclength did not work here? Obviously, because char
11282 fields when packed actually became 1 byte longer, when we also
11283 stored the string length as the first byte. */
11284
11285 208129 m_upd_buf_size =
11286 208129 table->s->reclength + table->s->max_key_length + MAX_REF_PARTS * 3;
11287
11288 208129 m_upd_buf = reinterpret_cast<uchar *>(
11289
1/2
✓ Branch 0 taken 208129 times.
✗ Branch 1 not taken.
208129 my_malloc(PSI_INSTRUMENT_ME, m_upd_buf_size, MYF(MY_WME)));
11290
11291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 208129 times.
208129 if (m_upd_buf == nullptr) {
11292 m_upd_buf_size = 0;
11293 return HA_ERR_OUT_OF_MEM;
11294 }
11295 }
11296
11297
1/2
✓ Branch 0 taken 14643846 times.
✗ Branch 1 not taken.
14643839 ha_statistic_increment(&System_status_var::ha_update_count);
11298
11299
5/10
✓ Branch 0 taken 14431969 times.
✓ Branch 1 taken 211877 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14431969 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 14643846 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 14643846 times.
14643846 if (UNIV_UNLIKELY(m_share && m_share->ib_table &&
11300 m_share->ib_table->is_corrupt))
11301 return HA_ERR_CRASHED;
11302
11303 upd_t *uvect;
11304
11305
2/2
✓ Branch 0 taken 14453296 times.
✓ Branch 1 taken 190550 times.
14643846 if (m_prebuilt->upd_node) {
11306 14453296 uvect = m_prebuilt->upd_node->update;
11307 } else {
11308
1/2
✓ Branch 0 taken 190554 times.
✗ Branch 1 not taken.
190550 uvect = row_get_prebuilt_update_vector(m_prebuilt);
11309 }
11310
11311 14643850 uvect->table = m_prebuilt->table;
11312 14643850 uvect->mysql_table = table;
11313
11314 /* Build an update vector from the modified fields in the rows
11315 (uses m_upd_buf of the handle) */
11316
11317
1/2
✓ Branch 0 taken 14643842 times.
✗ Branch 1 not taken.
14643850 error = calc_row_difference(uvect, old_row, new_row, table, m_upd_buf,
11318 m_upd_buf_size, m_prebuilt, m_user_thd);
11319
11320
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14643840 times.
14643842 if (error != DB_SUCCESS) {
11321 2 goto func_exit;
11322 }
11323
11324
8/10
✓ Branch 0 taken 14643841 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13034586 times.
✓ Branch 3 taken 1609255 times.
✓ Branch 4 taken 13034585 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 13034584 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 14643839 times.
14643840 if (!m_prebuilt->table->is_intrinsic() && TrxInInnoDB::is_aborted(trx)) {
11325
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 innobase_rollback(ht, m_user_thd, false);
11326
11327
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd);
11328 }
11329
11330 /* This is not a delete */
11331 14643839 m_prebuilt->upd_node->is_delete = false;
11332
11333
1/2
✓ Branch 0 taken 14643832 times.
✗ Branch 1 not taken.
14643839 error = innobase_srv_conc_enter_innodb(m_prebuilt);
11334
11335
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14643832 times.
14643832 if (error != DB_SUCCESS) {
11336 goto func_exit;
11337 }
11338
11339
1/2
✓ Branch 0 taken 14643834 times.
✗ Branch 1 not taken.
14643832 error = row_update_for_mysql((byte *)old_row, m_prebuilt);
11340
11341
2/2
✓ Branch 0 taken 7315714 times.
✓ Branch 1 taken 7328121 times.
14643834 if (dict_table_has_autoinc_col(m_prebuilt->table)) {
11342 7315714 new_counter = row_upd_get_new_autoinc_counter(
11343
1/2
✓ Branch 0 taken 7315714 times.
✗ Branch 1 not taken.
7315714 uvect, m_prebuilt->table->autoinc_field_no);
11344 } else {
11345 7328121 new_counter = 0;
11346 }
11347
11348 /* We should handle the case if the AUTOINC counter has been
11349 updated, we want to update the counter accordingly.
11350
11351 We need to do some special AUTOINC handling for the following case:
11352
11353 INSERT INTO t (c1,c2) VALUES(x,y) ON DUPLICATE KEY UPDATE ...
11354
11355 We need to use the AUTOINC counter that was actually used by
11356 MySQL in the UPDATE statement, which can be different from the
11357 value used in the INSERT statement. */
11358
11359
6/6
✓ Branch 0 taken 14643272 times.
✓ Branch 1 taken 563 times.
✓ Branch 2 taken 14642658 times.
✓ Branch 3 taken 614 times.
✓ Branch 4 taken 675 times.
✓ Branch 5 taken 14643160 times.
29286493 if (error == DB_SUCCESS &&
11360 14642658 (new_counter != 0 ||
11361
3/4
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 14642579 times.
✓ Branch 2 taken 79 times.
✗ Branch 3 not taken.
14642658 (table->next_number_field && new_row == table->record[0] &&
11362
4/6
✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 61 times.
✓ Branch 3 taken 18 times.
✓ Branch 4 taken 61 times.
✗ Branch 5 not taken.
140 thd_sql_command(m_user_thd) == SQLCOM_INSERT &&
11363 61 m_prebuilt->allow_duplicates()))) {
11364 ulonglong auto_inc;
11365 ulonglong col_max_value;
11366
11367
2/2
✓ Branch 0 taken 614 times.
✓ Branch 1 taken 61 times.
675 if (new_counter != 0) {
11368 614 auto_inc = new_counter;
11369 } else {
11370
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 ut_ad(table->next_number_field != nullptr);
11371
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 auto_inc = table->next_number_field->val_int();
11372 }
11373
11374 /* We need the upper limit of the col type to check for
11375 whether we update the table autoinc counter or not. */
11376
1/2
✓ Branch 0 taken 675 times.
✗ Branch 1 not taken.
675 col_max_value = table->found_next_number_field->get_max_int_value();
11377
11378
3/4
✓ Branch 0 taken 675 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 672 times.
✓ Branch 3 taken 3 times.
675 if (auto_inc <= col_max_value && auto_inc != 0) {
11379 ulonglong offset;
11380 ulonglong increment;
11381
11382 #ifdef WITH_WSREP
11383 /* Applier threads which are processing
11384 ROW events and don't go through server
11385 level autoinc processing, therefore
11386 m_prebuilt autoinc values don't get
11387 properly assigned. Fetch values from
11388 server side. */
11389
9/12
✓ Branch 0 taken 672 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 672 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 670 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 671 times.
672 if (wsrep_on(current_thd) && wsrep_thd_is_applying(m_user_thd)) {
11390
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 wsrep_thd_auto_increment_variables(current_thd, &offset, &increment);
11391 } else {
11392 671 offset = m_prebuilt->autoinc_offset;
11393 671 increment = m_prebuilt->autoinc_increment;
11394 }
11395 #else
11396 offset = m_prebuilt->autoinc_offset;
11397 increment = m_prebuilt->autoinc_increment;
11398 #endif /* WITH_WSREP */
11399
11400 auto_inc =
11401
1/2
✓ Branch 0 taken 672 times.
✗ Branch 1 not taken.
672 innobase_next_autoinc(auto_inc, 1, increment, offset, col_max_value);
11402
11403
1/2
✓ Branch 0 taken 672 times.
✗ Branch 1 not taken.
672 error = innobase_set_max_autoinc(auto_inc);
11404 }
11405 }
11406
11407
1/2
✓ Branch 0 taken 14643832 times.
✗ Branch 1 not taken.
14643835 innobase_srv_conc_exit_innodb(m_prebuilt);
11408
11409 14643834 func_exit:
11410
11411 err =
11412
1/2
✓ Branch 0 taken 14643834 times.
✗ Branch 1 not taken.
14643834 convert_error_code_to_mysql(error, m_prebuilt->table->flags, m_user_thd);
11413
11414 /* If success and no columns were updated. */
11415
4/4
✓ Branch 0 taken 14643269 times.
✓ Branch 1 taken 565 times.
✓ Branch 2 taken 7291702 times.
✓ Branch 3 taken 7351567 times.
14643834 if (err == 0 && uvect->n_fields == 0) {
11416 /* This is the same as success, but instructs
11417 MySQL that the row is not really updated and it
11418 should not increase the count of updated rows.
11419 This is fix for http://bugs.mysql.com/29157 */
11420 7291702 err = HA_ERR_RECORD_IS_THE_SAME;
11421
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7352130 times.
7352132 } else if (err == HA_FTS_INVALID_DOCID) {
11422
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(HA_FTS_INVALID_DOCID, MYF(0));
11423 }
11424
11425 /* Tell InnoDB server that there might be work for
11426 utility threads: */
11427
11428
1/2
✓ Branch 0 taken 14643839 times.
✗ Branch 1 not taken.
14643834 innobase_active_small();
11429
11430 #ifdef WITH_WSREP
11431 /* Append key
11432 a. there is no error in update
11433 b. exec mode is local
11434 (it is workload executor node and not replicator node)
11435 c. wsrep is enabled
11436 d. No consistency check enforced.
11437 e. Ensure that bin-logging is enabled.
11438 Either mysql bin-logging or emulated bin logging.
11439 TODO: We allow replication even if binlog-format = STATEMENT.
11440 This is needed by pt-table-checksum. Now it is not a good idea
11441 to open this hook for pt-table-checksum but it exist like this for
11442 while now so to maintain compatibility we continue to provide it.
11443 With that there comes another existing dependency. */
11444
7/8
✓ Branch 0 taken 7351572 times.
✓ Branch 1 taken 7292267 times.
✓ Branch 2 taken 7351572 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 620863 times.
✓ Branch 5 taken 6730709 times.
✓ Branch 6 taken 14022976 times.
✓ Branch 7 taken 620863 times.
14643839 if (!err && wsrep_do_replication(m_user_thd)) {
11445
3/8
✓ Branch 0 taken 620863 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 620863 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 620863 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
620863 DBUG_PRINT("wsrep", ("update row key"));
11446
2/4
✓ Branch 0 taken 620863 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 620863 times.
620863 if (wsrep_append_keys(m_user_thd,
11447
1/2
✓ Branch 0 taken 620863 times.
✗ Branch 1 not taken.
620863 wsrep_protocol_version >= 4
11448 ? WSREP_SERVICE_KEY_UPDATE
11449 : WSREP_SERVICE_KEY_EXCLUSIVE,
11450 old_row, new_row)) {
11451 DBUG_PRINT("wsrep", ("row key failed"));
11452 err = HA_ERR_INTERNAL_ERROR;
11453 /* If we hit error during append key then we mark for complete
11454 transaction rollback */
11455 thd_mark_for_rollback(m_user_thd);
11456 goto wsrep_error;
11457 }
11458 }
11459 14022976 wsrep_error:
11460 #endif /* WITH_WSREP */
11461
11462
5/10
✓ Branch 0 taken 14431954 times.
✓ Branch 1 taken 211885 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14431954 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 14643839 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 14643839 times.
14643839 if (UNIV_UNLIKELY(m_share && m_share->ib_table &&
11463 m_share->ib_table->is_corrupt))
11464 return HA_ERR_CRASHED;
11465
11466 14643839 return err;
11467 14643845 }
11468
11469 /** Deletes a row given as the parameter.
11470 @return error number or 0 */
11471
11472 9162579 int ha_innobase::delete_row(
11473 const uchar *record) /*!< in: a row in MySQL format */
11474 {
11475 dberr_t error;
11476
1/2
✓ Branch 0 taken 9162581 times.
✗ Branch 1 not taken.
9162579 trx_t *trx = thd_to_trx(m_user_thd);
11477
1/2
✓ Branch 0 taken 9162580 times.
✗ Branch 1 not taken.
9162581 TrxInInnoDB trx_in_innodb(trx);
11478
11479
1/2
✓ Branch 0 taken 9162581 times.
✗ Branch 1 not taken.
9162580 DBUG_TRACE;
11480
11481
5/10
✓ Branch 0 taken 9162581 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9162581 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9162581 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 9162581 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 9162581 times.
9162581 if (!m_prebuilt->table->is_intrinsic() && trx_in_innodb.is_aborted()) {
11482 innobase_rollback(ht, m_user_thd, false);
11483
11484 return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd);
11485 }
11486
11487
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9162579 times.
9162581 ut_a(m_prebuilt->trx == trx);
11488
11489
6/8
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 9162574 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✓ Branch 7 taken 9162574 times.
9162579 if (high_level_read_only && !m_prebuilt->table->is_intrinsic()) {
11490
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 ib_senderrf(ha_thd(), IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE);
11491 5 return HA_ERR_TABLE_READONLY;
11492
2/4
✓ Branch 0 taken 9162575 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9162575 times.
9162574 } else if (!trx_is_started(trx)) {
11493 ++trx->will_lock;
11494 }
11495
11496
1/2
✓ Branch 0 taken 9162576 times.
✗ Branch 1 not taken.
9162575 ha_statistic_increment(&System_status_var::ha_delete_count);
11497
11498
5/10
✓ Branch 0 taken 9079721 times.
✓ Branch 1 taken 82855 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9079721 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 9162576 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 9162576 times.
9162576 if (UNIV_UNLIKELY(m_share && m_share->ib_table &&
11499 m_share->ib_table->is_corrupt))
11500 return HA_ERR_CRASHED;
11501
11502
2/2
✓ Branch 0 taken 126065 times.
✓ Branch 1 taken 9036511 times.
9162576 if (!m_prebuilt->upd_node) {
11503
1/2
✓ Branch 0 taken 126066 times.
✗ Branch 1 not taken.
126065 row_get_prebuilt_update_vector(m_prebuilt);
11504 }
11505
11506 /* This is a delete */
11507
11508 9162577 m_prebuilt->upd_node->is_delete = true;
11509
11510
1/2
✓ Branch 0 taken 9162576 times.
✗ Branch 1 not taken.
9162577 error = innobase_srv_conc_enter_innodb(m_prebuilt);
11511
11512
1/2
✓ Branch 0 taken 9162576 times.
✗ Branch 1 not taken.
9162576 if (error == DB_SUCCESS) {
11513
1/2
✓ Branch 0 taken 9162575 times.
✗ Branch 1 not taken.
9162576 error = row_update_for_mysql((byte *)record, m_prebuilt);
11514
1/2
✓ Branch 0 taken 9162575 times.
✗ Branch 1 not taken.
9162575 innobase_srv_conc_exit_innodb(m_prebuilt);
11515 }
11516
11517 /* Tell the InnoDB server that there might be work for
11518 utility threads: */
11519
11520
1/2
✓ Branch 0 taken 9162575 times.
✗ Branch 1 not taken.
9162575 innobase_active_small();
11521
11522 #ifdef WITH_WSREP
11523 /* Append key
11524 a. there is no error in delete
11525 b. exec mode is local
11526 (it is workload executor node and not replicator node)
11527 c. wsrep is enabled
11528 d. No consistency check enforced.
11529 e. Ensure that bin-logging is enabled.
11530 Either mysql bin-logging or emulated bin logging.
11531 TODO: We allow replication even if binlog-format = STATEMENT.
11532 This is needed by pt-table-checksum. Now it is not a god idea
11533 to open this hook for pt-table-checksum but it exist like this for
11534 while now so to maintain compatibility we continue to provide it.
11535 With that there comes another existing dependency. */
11536
7/8
✓ Branch 0 taken 9162507 times.
✓ Branch 1 taken 68 times.
✓ Branch 2 taken 9162507 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 22259 times.
✓ Branch 5 taken 9140248 times.
✓ Branch 6 taken 9140316 times.
✓ Branch 7 taken 22259 times.
9162575 if (error == DB_SUCCESS && wsrep_do_replication(m_user_thd)) {
11537
2/4
✓ Branch 0 taken 22259 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 22259 times.
22259 if (wsrep_append_keys(m_user_thd, WSREP_SERVICE_KEY_EXCLUSIVE, record,
11538 NULL)) {
11539 DBUG_PRINT("wsrep", ("delete fail"));
11540 error = DB_ERROR;
11541 /* If we hit error during append key then we mark for complete
11542 transaction rollback */
11543 thd_mark_for_rollback(m_user_thd);
11544 goto wsrep_error;
11545 }
11546 }
11547
11548 9140316 wsrep_error:
11549 #endif /* WITH_WSREP */
11550
11551
5/10
✓ Branch 0 taken 9079720 times.
✓ Branch 1 taken 82855 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9079720 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 9162575 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 9162575 times.
9162575 if (UNIV_UNLIKELY(m_share && m_share->ib_table &&
11552 m_share->ib_table->is_corrupt))
11553 return HA_ERR_CRASHED;
11554
11555
1/2
✓ Branch 0 taken 9162575 times.
✗ Branch 1 not taken.
9162575 return convert_error_code_to_mysql(error, m_prebuilt->table->flags,
11556 9162575 m_user_thd);
11557 9162580 }
11558
11559 /** Delete all rows from the table.
11560 @retval HA_ERR_WRONG_COMMAND if the table is transactional
11561 @retval 0 on success */
11562 63501 int ha_innobase::delete_all_rows() {
11563
1/2
✓ Branch 0 taken 63501 times.
✗ Branch 1 not taken.
63501 DBUG_TRACE;
11564
11565
3/4
✓ Branch 0 taken 63501 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2990 times.
✓ Branch 3 taken 60511 times.
63501 if (!m_prebuilt->table->is_intrinsic()) {
11566 /* Transactional tables should use truncate(). */
11567 2990 return HA_ERR_WRONG_COMMAND;
11568 }
11569
11570
1/2
✓ Branch 0 taken 60511 times.
✗ Branch 1 not taken.
60511 row_delete_all_rows(m_prebuilt->table);
11571
11572
1/2
✓ Branch 0 taken 60511 times.
✗ Branch 1 not taken.
60511 dict_stats_update(m_prebuilt->table, DICT_STATS_EMPTY_TABLE);
11573
11574 60511 return 0;
11575 63501 }
11576
11577 /** Removes a new lock set on a row, if it was not read optimistically. This can
11578 be called after a row has been read in the processing of an UPDATE or a DELETE
11579 query, when the record doesn't match the WHERE condition. */
11580
11581 55779001 void ha_innobase::unlock_row(void) {
11582
1/2
✓ Branch 0 taken 55779001 times.
✗ Branch 1 not taken.
55779001 DBUG_TRACE;
11583
11584 /* Consistent read does not take any locks, thus there is
11585 nothing to unlock. There is no locking for intrinsic table. */
11586
11587
4/4
✓ Branch 0 taken 26860781 times.
✓ Branch 1 taken 28918220 times.
✓ Branch 2 taken 28918220 times.
✓ Branch 3 taken 26860781 times.
82639782 if (m_prebuilt->select_lock_type == LOCK_NONE ||
11588
2/4
✓ Branch 0 taken 26860781 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 26860781 times.
26860781 m_prebuilt->table->is_intrinsic()) {
11589 28918220 return;
11590 }
11591
11592
1/2
✓ Branch 0 taken 26860781 times.
✗ Branch 1 not taken.
26860781 TrxInInnoDB trx_in_innodb(m_prebuilt->trx);
11593
11594
2/4
✓ Branch 0 taken 26860781 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 26860781 times.
26860781 if (trx_in_innodb.is_aborted()) {
11595 return;
11596 }
11597
11598
2/4
✓ Branch 0 taken 26860781 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 26860781 times.
26860781 ut_ad(!m_prebuilt->table->is_intrinsic());
11599
11600 /* Ideally, this assert must be in the beginning of the function.
11601 But there are some calls to this function from the SQL layer when the
11602 transaction is in state TRX_STATE_NOT_STARTED. The check on
11603 m_prebuilt->select_lock_type above gets around this issue. */
11604
11605
3/10
✓ Branch 0 taken 26860781 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 26860781 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 26860781 times.
26860781 ut_ad(trx_state_eq(m_prebuilt->trx, TRX_STATE_ACTIVE) ||
11606 trx_state_eq(m_prebuilt->trx, TRX_STATE_FORCED_ROLLBACK));
11607
11608 /* The purpose of unlock_row() is to release locks held on non-matching row
11609 found during most recent row_search_mvcc() call.
11610 In higher isolation levels row_try_unlock() is a no-op, as we only set the
11611 m_prebuilt->new_rec_lock[i] when trx->releases_non_matching_rows().
11612 In lower isolation levels row_try_unlock() will remove the record locks which
11613 were newly created during the most recent row_search_mvcc() (the record locks
11614 which were merely reused, are not released as they are still needed).
11615 @see handler::was_semi_consistent_read() for great explanation of what
11616 semi-consistent read mode is all about and why we don't call row_try_unlock()
11617 in case of ROW_READ_DID_SEMI_CONSISTENT, and reset the flag instead; in short
11618 a successful semi-consistent read means we didn't acquire any lock, so don't
11619 need to unlock anything if the row doesn't match the query. */
11620
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 26860742 times.
26860781 if (m_prebuilt->row_read_type == ROW_READ_DID_SEMI_CONSISTENT) {
11621
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 ut_ad(m_prebuilt->new_rec_locks_count() == 0);
11622 39 m_prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
11623 }
11624
1/2
✓ Branch 0 taken 26860781 times.
✗ Branch 1 not taken.
26860781 m_prebuilt->try_unlock(false);
11625
3/4
✓ Branch 0 taken 26860781 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26860781 times.
✓ Branch 3 taken 28918220 times.
55779001 }
11626
11627 /* See handler.h and row0mysql.h for docs on this function. */
11628
11629 3594254 bool ha_innobase::was_semi_consistent_read(void) {
11630 3594254 return (m_prebuilt->row_read_type == ROW_READ_DID_SEMI_CONSISTENT);
11631 }
11632
11633 /* See handler.h and row0mysql.h for docs on this function. */
11634
11635 408780 void ha_innobase::try_semi_consistent_read(bool yes) {
11636
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 408885 times.
408780 ut_a(m_prebuilt->trx == thd_to_trx(ha_thd()));
11637
11638
6/6
✓ Branch 0 taken 196984 times.
✓ Branch 1 taken 211901 times.
✓ Branch 2 taken 242 times.
✓ Branch 3 taken 196737 times.
✓ Branch 4 taken 242 times.
✓ Branch 5 taken 408638 times.
408885 if (yes && m_prebuilt->trx->allow_semi_consistent()) {
11639 242 m_prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
11640
11641 } else {
11642 408638 m_prebuilt->row_read_type = ROW_READ_WITH_LOCKS;
11643 }
11644 408880 }
11645
11646 /** Initializes a handle to use an index.
11647 @return 0 or error number */
11648 102552345 int ha_innobase::index_init(uint keynr, /*!< in: key (index) number */
11649 bool) /*!< in: 1 if result
11650 MUST be sorted
11651 according to index */
11652 {
11653
1/2
✓ Branch 0 taken 102553218 times.
✗ Branch 1 not taken.
102552345 DBUG_TRACE;
11654
11655
1/2
✓ Branch 0 taken 102553300 times.
✗ Branch 1 not taken.
205106534 return change_active_index(keynr);
11656 102553300 }
11657
11658 /** Currently does nothing.
11659 @return 0 */
11660
11661 105306167 int ha_innobase::index_end(void) {
11662
1/2
✓ Branch 0 taken 105306192 times.
✗ Branch 1 not taken.
105306167 DBUG_TRACE;
11663
11664
2/2
✓ Branch 0 taken 55853 times.
✓ Branch 1 taken 105250339 times.
105306192 if (m_prebuilt->index->last_sel_cur) {
11665
1/2
✓ Branch 0 taken 55853 times.
✗ Branch 1 not taken.
55853 m_prebuilt->index->last_sel_cur->release();
11666 }
11667
11668 105306192 active_index = MAX_KEY;
11669
11670 105306192 in_range_check_pushed_down = false;
11671
11672
1/2
✓ Branch 0 taken 105306187 times.
✗ Branch 1 not taken.
105306192 m_ds_mrr.dsmrr_close();
11673
11674 105306195 return 0;
11675 105306187 }
11676
11677 /** Converts a search mode flag understood by MySQL to a flag understood
11678 by InnoDB. */
11679 81101645 page_cur_mode_t convert_search_mode_to_innobase(ha_rkey_function find_flag) {
11680
9/12
✓ Branch 0 taken 75743761 times.
✓ Branch 1 taken 5323078 times.
✓ Branch 2 taken 27150 times.
✓ Branch 3 taken 6900 times.
✓ Branch 4 taken 240 times.
✓ Branch 5 taken 311 times.
✓ Branch 6 taken 84 times.
✓ Branch 7 taken 56 times.
✓ Branch 8 taken 115 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
81101645 switch (find_flag) {
11681 75743761 case HA_READ_KEY_EXACT:
11682 /* this does not require the index to be UNIQUE */
11683 case HA_READ_KEY_OR_NEXT:
11684 75743761 return (PAGE_CUR_GE);
11685 5323078 case HA_READ_AFTER_KEY:
11686 5323078 return (PAGE_CUR_G);
11687 27150 case HA_READ_BEFORE_KEY:
11688 27150 return (PAGE_CUR_L);
11689 6900 case HA_READ_KEY_OR_PREV:
11690 case HA_READ_PREFIX_LAST:
11691 case HA_READ_PREFIX_LAST_OR_PREV:
11692 6900 return (PAGE_CUR_LE);
11693 240 case HA_READ_MBR_CONTAIN:
11694 240 return (PAGE_CUR_CONTAIN);
11695 311 case HA_READ_MBR_INTERSECT:
11696 311 return (PAGE_CUR_INTERSECT);
11697 84 case HA_READ_MBR_WITHIN:
11698 84 return (PAGE_CUR_WITHIN);
11699 56 case HA_READ_MBR_DISJOINT:
11700 56 return (PAGE_CUR_DISJOINT);
11701 115 case HA_READ_MBR_EQUAL:
11702 115 return (PAGE_CUR_MBR_EQUAL);
11703 case HA_READ_PREFIX:
11704 return (PAGE_CUR_UNSUPP);
11705 case HA_READ_INVALID:
11706 return (PAGE_CUR_UNSUPP);
11707 /* do not use "default:" in order to produce a gcc warning:
11708 enumeration value '...' not handled in switch
11709 (if -Wswitch or -Wall is used) */
11710 }
11711
11712 my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "this functionality");
11713
11714 return (PAGE_CUR_UNSUPP);
11715 }
11716
11717 #if defined(UNIV_DEBUG) && !defined(UNIV_DEBUG_VALGRIND)
11718 413377 static bool template_new_is_valid(mysql_row_templ_t *t_new,
11719 const mysql_row_templ_t *t_saved,
11720 int n_template) {
11721 /* Percona might modify the template field `rec_field_no`, after its creation,
11722 in row0sel.cc:use_secondary_index.
11723 In order to compare the new template and the previous one, we overwrite
11724 `rec_field_no`.
11725 The new template is discarded and used just for debug purposes so we do not
11726 need to restore the previous value. */
11727
2/2
✓ Branch 0 taken 1032331 times.
✓ Branch 1 taken 413377 times.
1445708 for (auto i = 0; i < n_template; ++i) {
11728 1032331 auto *templ_new = t_new + i;
11729 1032331 const auto *templ_saved = t_saved + i;
11730 1032331 templ_new->rec_field_no = templ_saved->rec_field_no;
11731 }
11732
11733 413377 return !memcmp(t_new, t_saved, n_template * sizeof(mysql_row_templ_t));
11734 }
11735 #endif
11736
11737 /*
11738 BACKGROUND INFO: HOW A SELECT SQL QUERY IS EXECUTED
11739 ---------------------------------------------------
11740 The following does not cover all the details, but explains how we determine
11741 the start of a new SQL statement, and what is associated with it.
11742
11743 For each table in the database the MySQL interpreter may have several
11744 table handle instances in use, also in a single SQL query. For each table
11745 handle instance there is an InnoDB 'm_prebuilt' struct which contains most
11746 of the InnoDB data associated with this table handle instance.
11747
11748 A) if the user has not explicitly set any MySQL table level locks:
11749
11750 1) MySQL calls ::external_lock to set an 'intention' table level lock on
11751 the table of the handle instance. There we set
11752 m_prebuilt->sql_stat_start = true. The flag sql_stat_start should be set
11753 true if we are taking this table handle instance to use in a new SQL
11754 statement issued by the user. We also increment trx->n_mysql_tables_in_use.
11755
11756 2) If m_prebuilt->sql_stat_start == true we 'pre-compile' the MySQL search
11757 instructions to m_prebuilt->template of the table handle instance in
11758 ::index_read. The template is used to save CPU time in large joins.
11759
11760 3) In row_search_for_mysql, if m_prebuilt->sql_stat_start is true, we
11761 allocate a new consistent read view for the trx if it does not yet have one,
11762 or in the case of a locking read, set an InnoDB 'intention' table level
11763 lock on the table.
11764
11765 4) We do the SELECT. MySQL may repeatedly call ::index_read for the
11766 same table handle instance, if it is a join.
11767
11768 5) When the SELECT ends, MySQL removes its intention table level locks
11769 in ::external_lock. When trx->n_mysql_tables_in_use drops to zero,
11770 (a) we execute a COMMIT there if the autocommit is on,
11771 (b) we also release possible 'SQL statement level resources' InnoDB may
11772 have for this SQL statement. The MySQL interpreter does NOT execute
11773 autocommit for pure read transactions, though it should. That is why the
11774 table handler in that case has to execute the COMMIT in ::external_lock.
11775
11776 B) If the user has explicitly set MySQL table level locks, then MySQL
11777 does NOT call ::external_lock at the start of the statement. To determine
11778 when we are at the start of a new SQL statement we at the start of
11779 ::index_read also compare the query id to the latest query id where the
11780 table handle instance was used. If it has changed, we know we are at the
11781 start of a new SQL statement. Since the query id can theoretically
11782 overwrap, we use this test only as a secondary way of determining the
11783 start of a new SQL statement. */
11784
11785 /** Positions an index cursor to the index specified in the handle. Fetches the
11786 row if any.
11787 @return 0, HA_ERR_KEY_NOT_FOUND, or error number */
11788
11789 80058933 int ha_innobase::index_read(
11790 uchar *buf, /*!< in/out: buffer for the returned
11791 row */
11792 const uchar *key_ptr, /*!< in: key value; if this is NULL
11793 we position the cursor at the
11794 start or end of index; this can
11795 also contain an InnoDB row id, in
11796 which case key_len is the InnoDB
11797 row id length; the key value can
11798 also be a prefix of a full key value,
11799 and the last column can be a prefix
11800 of a full column */
11801 uint key_len, /*!< in: key value length */
11802 enum ha_rkey_function find_flag) /*!< in: search flags from my_base.h */
11803 {
11804
1/2
✓ Branch 0 taken 80059438 times.
✗ Branch 1 not taken.
80058933 DBUG_TRACE;
11805
3/4
✓ Branch 0 taken 77293215 times.
✓ Branch 1 taken 2766223 times.
✓ Branch 2 taken 77293213 times.
✗ Branch 3 not taken.
80059438 DEBUG_SYNC_C("ha_innobase_index_read_begin");
11806
11807
3/4
✓ Branch 0 taken 80059410 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
✓ Branch 3 taken 80059414 times.
80059436 ut_a(m_prebuilt->trx == thd_to_trx(m_user_thd));
11808
4/6
✓ Branch 0 taken 4845730 times.
✓ Branch 1 taken 75213684 times.
✓ Branch 2 taken 4845730 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 80059364 times.
80059414 ut_ad(key_len != 0 || find_flag != HA_READ_KEY_EXACT);
11809
11810
1/2
✓ Branch 0 taken 80059375 times.
✗ Branch 1 not taken.
80059364 ha_statistic_increment(&System_status_var::ha_read_key_count);
11811
11812
8/14
✓ Branch 0 taken 80059391 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 79417039 times.
✓ Branch 3 taken 642352 times.
✓ Branch 4 taken 79417027 times.
✓ Branch 5 taken 642348 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 79417027 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 80059375 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 80059375 times.
80059375 if (UNIV_UNLIKELY(srv_pass_corrupt_table <= 1 && m_share &&
11813 m_share->ib_table && m_share->ib_table->is_corrupt)) {
11814 return HA_ERR_CRASHED;
11815 }
11816
11817 80059375 dict_index_t *index = m_prebuilt->index;
11818
11819
6/8
✓ Branch 0 taken 80059372 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 80059334 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 25 times.
✓ Branch 5 taken 80059309 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 80059337 times.
80059375 if (index == nullptr || index->is_corrupted()) {
11820 m_prebuilt->index_usable = false;
11821 return HA_ERR_CRASHED;
11822 }
11823
11824
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80059337 times.
80059337 if (!m_prebuilt->index_usable) {
11825 return index->is_corrupted() ? HA_ERR_INDEX_CORRUPT
11826 : HA_ERR_TABLE_DEF_CHANGED;
11827 }
11828
11829
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80059337 times.
80059337 if (index->type & DICT_FTS) {
11830 return HA_ERR_KEY_NOT_FOUND;
11831 }
11832
11833 /* For R-Tree index, we will always place the page lock to
11834 pages being searched */
11835
3/4
✓ Branch 0 taken 80059309 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 241 times.
✓ Branch 3 taken 80059068 times.
80059337 if (dict_index_is_spatial(index)) {
11836 241 ++m_prebuilt->trx->will_lock;
11837 }
11838
11839 /* Note that if the index for which the search template is built is not
11840 necessarily m_prebuilt->index, but can also be the clustered index */
11841
11842
7/8
✓ Branch 0 taken 54301703 times.
✓ Branch 1 taken 25757606 times.
✓ Branch 2 taken 54301447 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 53888268 times.
✓ Branch 5 taken 413179 times.
✓ Branch 6 taken 53888333 times.
✓ Branch 7 taken 26170720 times.
80059309 if (m_prebuilt->sql_stat_start && !can_reuse_mysql_template()) {
11843
1/2
✓ Branch 0 taken 53888621 times.
✗ Branch 1 not taken.
53888333 build_template(false);
11844 }
11845
11846 #if defined(UNIV_DEBUG) && !defined(UNIV_DEBUG_VALGRIND)
11847 /* valgrind complains about some of uninitialized bytes. skip it for now. */
11848
7/8
✓ Branch 0 taken 54301826 times.
✓ Branch 1 taken 25757515 times.
✓ Branch 2 taken 54301854 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 413377 times.
✓ Branch 5 taken 53888477 times.
✓ Branch 6 taken 413377 times.
✓ Branch 7 taken 79645992 times.
80059341 if (m_prebuilt->sql_stat_start && can_reuse_mysql_template()) {
11849 /* confirm mysql_template contents are same */
11850 413377 const auto n_template_save = m_prebuilt->n_template;
11851 413377 mysql_row_templ_t *mysql_template_save = m_prebuilt->mysql_template;
11852 413377 m_prebuilt->mysql_template = nullptr;
11853
1/2
✓ Branch 0 taken 413377 times.
✗ Branch 1 not taken.
413377 build_template(false);
11854
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 413377 times.
413377 ut_a(m_prebuilt->n_template == n_template_save);
11855
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 413377 times.
413377 ut_a(template_new_is_valid(m_prebuilt->mysql_template, mysql_template_save,
11856 n_template_save));
11857 413377 ut::free(m_prebuilt->mysql_template);
11858 413377 m_prebuilt->mysql_template = mysql_template_save;
11859 }
11860 #endif /* UNIV_DEBUG && !UNIV_DEBUG_VALGRIND */
11861
11862
2/2
✓ Branch 0 taken 75213523 times.
✓ Branch 1 taken 4845846 times.
80059369 if (key_ptr != nullptr) {
11863 /* Convert the search key value to InnoDB format into
11864 m_prebuilt->search_tuple */
11865
11866 75213523 row_sel_convert_mysql_key_to_innobase(
11867 75213523 m_prebuilt->search_tuple, m_prebuilt->srch_key_val1,
11868
1/2
✓ Branch 0 taken 75213567 times.
✗ Branch 1 not taken.
75213523 m_prebuilt->srch_key_val_len, index, key_ptr, key_len);
11869
11870
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75213567 times.
75213567 assert(m_prebuilt->search_tuple->n_fields > 0);
11871 } else {
11872 /* We position the cursor to the last or the first entry
11873 in the index */
11874
11875
1/2
✓ Branch 0 taken 4845708 times.
✗ Branch 1 not taken.
4845846 dtuple_set_n_fields(m_prebuilt->search_tuple, 0);
11876 }
11877
11878
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 80059116 times.
80059275 ut_ad(m_prebuilt->m_mysql_handler == this);
11879 80059116 m_prebuilt->m_stop_tuple_found = false;
11880
6/6
✓ Branch 0 taken 405682 times.
✓ Branch 1 taken 79653434 times.
✓ Branch 2 taken 359595 times.
✓ Branch 3 taken 46087 times.
✓ Branch 4 taken 359595 times.
✓ Branch 5 taken 79699521 times.
80059116 if (end_range != nullptr && m_prebuilt->is_reading_range()) {
11881 359595 row_sel_convert_mysql_key_to_innobase(
11882 359595 m_prebuilt->m_stop_tuple, m_prebuilt->srch_key_val2,
11883
1/2
✓ Branch 0 taken 359625 times.
✗ Branch 1 not taken.
359595 m_prebuilt->srch_key_val_len, index, end_range->key, end_range->length);
11884 } else {
11885
1/2
✓ Branch 0 taken 79699514 times.
✗ Branch 1 not taken.
79699521 dtuple_set_n_fields(m_prebuilt->m_stop_tuple, 0);
11886 }
11887
11888
1/2
✓ Branch 0 taken 80058832 times.
✗ Branch 1 not taken.
80059139 page_cur_mode_t mode = convert_search_mode_to_innobase(find_flag);
11889
11890 80058832 ulint match_mode = 0;
11891
11892
2/2
✓ Branch 0 taken 75072388 times.
✓ Branch 1 taken 4986444 times.
80058832 if (find_flag == HA_READ_KEY_EXACT) {
11893 75072388 match_mode = ROW_SEL_EXACT;
11894
11895
2/2
✓ Branch 0 taken 2331 times.
✓ Branch 1 taken 4984113 times.
4986444 } else if (find_flag == HA_READ_PREFIX_LAST) {
11896 2331 match_mode = ROW_SEL_EXACT_PREFIX;
11897 }
11898
11899 80058832 m_last_match_mode = (uint)match_mode;
11900
11901 dberr_t ret;
11902
11903
1/2
✓ Branch 0 taken 80059086 times.
✗ Branch 1 not taken.
80058832 if (mode != PAGE_CUR_UNSUPP) {
11904
1/2
✓ Branch 0 taken 80058918 times.
✗ Branch 1 not taken.
80059086 ret = innobase_srv_conc_enter_innodb(m_prebuilt);
11905
11906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80058918 times.
80058918 if (ret != DB_SUCCESS) {
11907 return convert_error_code_to_mysql(ret, m_prebuilt->table->flags,
11908 m_user_thd);
11909 }
11910
11911
3/4
✓ Branch 0 taken 80059158 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 71224282 times.
✓ Branch 3 taken 8834876 times.
80058918 if (!m_prebuilt->table->is_intrinsic()) {
11912
3/4
✓ Branch 0 taken 71224283 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 71224282 times.
71224282 if (TrxInInnoDB::is_aborted(m_prebuilt->trx)) {
11913
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 innobase_rollback(ht, m_user_thd, false);
11914
11915
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd);
11916 }
11917
11918
1/2
✓ Branch 0 taken 71224035 times.
✗ Branch 1 not taken.
71224282 m_prebuilt->ins_sel_stmt = thd_is_ins_sel_stmt(m_user_thd);
11919
11920
1/2
✓ Branch 0 taken 71224499 times.
✗ Branch 1 not taken.
71224035 ret = row_search_mvcc(buf, mode, m_prebuilt, match_mode, 0);
11921
11922 } else {
11923
1/2
✓ Branch 0 taken 8834923 times.
✗ Branch 1 not taken.
8834876 m_prebuilt->session = thd_to_innodb_session(m_user_thd);
11924
11925
1/2
✓ Branch 0 taken 8834923 times.
✗ Branch 1 not taken.
8834923 ret = row_search_no_mvcc(buf, mode, m_prebuilt, match_mode, 0);
11926 }
11927
11928
1/2
✓ Branch 0 taken 80059758 times.
✗ Branch 1 not taken.
80059422 innobase_srv_conc_exit_innodb(m_prebuilt);
11929 } else {
11930 ret = DB_UNSUPPORTED;
11931 }
11932
11933
9/14
✓ Branch 0 taken 80059488 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 79417145 times.
✓ Branch 3 taken 642343 times.
✓ Branch 4 taken 79417128 times.
✓ Branch 5 taken 642376 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 79417128 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 80059504 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 80059504 times.
80059504 if (UNIV_UNLIKELY(srv_pass_corrupt_table <= 1 && m_share &&
11934 m_share->ib_table && m_share->ib_table->is_corrupt)) {
11935 return HA_ERR_CRASHED;
11936 }
11937
11938
2/4
✓ Branch 0 taken 80059503 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 80059503 times.
80059504 DBUG_EXECUTE_IF("ib_select_query_failure", ret = DB_ERROR;);
11939
11940 int error;
11941
11942
5/6
✓ Branch 0 taken 59431709 times.
✓ Branch 1 taken 19799868 times.
✓ Branch 2 taken 827412 times.
✓ Branch 3 taken 167 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 347 times.
80059503 switch (ret) {
11943 59431709 case DB_SUCCESS:
11944 59431709 error = 0;
11945
2/2
✓ Branch 0 taken 44538112 times.
✓ Branch 1 taken 14893597 times.
59431709 if (m_prebuilt->table->is_system_table) {
11946
1/2
✓ Branch 0 taken 44538118 times.
✗ Branch 1 not taken.
44538105 srv_stats.n_system_rows_read.add(
11947
1/2
✓ Branch 0 taken 44538105 times.
✗ Branch 1 not taken.
44538112 thd_get_thread_id(m_prebuilt->trx->mysql_thd), 1);
11948 } else {
11949
2/4
✓ Branch 0 taken 14893598 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14893600 times.
✗ Branch 3 not taken.
14893597 srv_stats.n_rows_read.add(thd_get_thread_id(m_prebuilt->trx->mysql_thd),
11950 1);
11951 }
11952 59431718 break;
11953
11954 19799868 case DB_RECORD_NOT_FOUND:
11955 19799868 error = HA_ERR_KEY_NOT_FOUND;
11956 19799868 break;
11957
11958 827412 case DB_END_OF_INDEX:
11959 827412 error = HA_ERR_KEY_NOT_FOUND;
11960 827412 break;
11961
11962 167 case DB_TABLESPACE_DELETED:
11963 167 ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR,
11964
1/2
✓ Branch 0 taken 167 times.
✗ Branch 1 not taken.
167 ER_TABLESPACE_DISCARDED, table->s->table_name.str);
11965
11966 167 error = HA_ERR_NO_SUCH_TABLE;
11967 167 break;
11968
11969 case DB_TABLESPACE_NOT_FOUND:
11970
11971 ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR,
11972 ER_TABLESPACE_MISSING, table->s->table_name.str);
11973
11974 error = HA_ERR_TABLESPACE_MISSING;
11975 break;
11976
11977 347 default:
11978
1/2
✓ Branch 0 taken 334 times.
✗ Branch 1 not taken.
347 error = convert_error_code_to_mysql(ret, m_prebuilt->table->flags,
11979 m_user_thd);
11980
11981 334 break;
11982 }
11983
11984 80059499 return error;
11985 80059500 }
11986
11987 /** The following functions works like index_read, but it find the last
11988 row with the current key value or prefix.
11989 @return 0, HA_ERR_KEY_NOT_FOUND, or an error code */
11990
11991 492 int ha_innobase::index_read_last(
11992 uchar *buf, /*!< out: fetched row */
11993 const uchar *key_ptr, /*!< in: key value, or a prefix of a full
11994 key value */
11995 uint key_len) /*!< in: length of the key val or prefix
11996 in bytes */
11997 {
11998 492 return (index_read(buf, key_ptr, key_len, HA_READ_PREFIX_LAST));
11999 }
12000
12001 /** Get the index for a handle. Does not change active index.
12002 @return NULL or index instance. */
12003
12004 132774020 dict_index_t *ha_innobase::innobase_get_index(
12005 uint keynr) /*!< in: use this index; MAX_KEY means always
12006 clustered index, even if it was internally
12007 generated by InnoDB */
12008 {
12009 KEY *key;
12010 dict_index_t *index;
12011
12012
1/2
✓ Branch 0 taken 132775182 times.
✗ Branch 1 not taken.
132774020 DBUG_TRACE;
12013
12014
3/4
✓ Branch 0 taken 132327887 times.
✓ Branch 1 taken 447295 times.
✓ Branch 2 taken 132327993 times.
✗ Branch 3 not taken.
132775182 if (keynr != MAX_KEY && table->s->keys > 0) {
12015 132327993 key = table->key_info + keynr;
12016
12017 132327993 index = innobase_index_lookup(m_share, keynr);
12018
12019
1/2
✓ Branch 0 taken 132327669 times.
✗ Branch 1 not taken.
132327397 if (index != nullptr) {
12020
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 132326580 times.
132327669 ut_a(ut_strcmp(index->name, key->name) == 0);
12021 } else {
12022 /* Can't find index with keynr in the translation
12023 table. Only print message if the index translation
12024 table exists */
12025 if (m_share->idx_trans_tbl.index_mapping != nullptr) {
12026 log_errlog(WARNING_LEVEL, ER_INNODB_FAILED_TO_FIND_IDX_WITH_KEY_NO,
12027 key ? key->name : "NULL", keynr,
12028 m_prebuilt->table->name.m_name);
12029 }
12030
12031 index = dict_table_get_index_on_name(m_prebuilt->table, key->name);
12032 }
12033 } else {
12034 447189 key = nullptr;
12035
1/2
✓ Branch 0 taken 447213 times.
✗ Branch 1 not taken.
447189 index = m_prebuilt->table->first_index();
12036 }
12037
12038
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 132773793 times.
132773793 if (index == nullptr) {
12039 log_errlog(ERROR_LEVEL, ER_INNODB_FAILED_TO_FIND_IDX_FROM_DICT_CACHE, keynr,
12040 key ? key->name : "NULL", m_prebuilt->table->name.m_name);
12041 }
12042
12043 132775167 return index;
12044 132773793 }
12045
12046 /** Changes the active index of a handle.
12047 @return 0 or error code */
12048 106895280 int ha_innobase::change_active_index(
12049 uint keynr) /*!< in: use this index; MAX_KEY means always clustered
12050 index, even if it was internally generated by
12051 InnoDB */
12052 {
12053
1/2
✓ Branch 0 taken 106895879 times.
✗ Branch 1 not taken.
106895280 DBUG_TRACE;
12054
12055
9/14
✓ Branch 0 taken 106895780 times.
✓ Branch 1 taken 99 times.
✓ Branch 2 taken 106895763 times.
✓ Branch 3 taken 17 times.
✓ Branch 4 taken 106895763 times.
✓ Branch 5 taken 116 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 106895763 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 106895879 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 106895879 times.
106895879 if (UNIV_UNLIKELY(srv_pass_corrupt_table <= 1 && m_share &&
12056 m_share->ib_table && m_share->ib_table->is_corrupt))
12057 return HA_ERR_CRASHED;
12058
12059
2/4
✓ Branch 0 taken 106895829 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 106895821 times.
106895879 ut_ad(m_user_thd == ha_thd());
12060
2/4
✓ Branch 0 taken 106895508 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 106895666 times.
106895821 ut_a(m_prebuilt->trx == thd_to_trx(m_user_thd));
12061
12062
1/2
✓ Branch 0 taken 106895636 times.
✗ Branch 1 not taken.
106895666 TrxInInnoDB trx_in_innodb(m_prebuilt->trx);
12063
12064
8/10
✓ Branch 0 taken 106895560 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 106837580 times.
✓ Branch 3 taken 57980 times.
✓ Branch 4 taken 106837601 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 106837599 times.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 106895579 times.
106895636 if (!m_prebuilt->table->is_intrinsic() && trx_in_innodb.is_aborted()) {
12065
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 innobase_rollback(ht, m_user_thd, false);
12066
12067
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd);
12068 }
12069
12070 106895579 active_index = keynr;
12071
12072
1/2
✓ Branch 0 taken 106895888 times.
✗ Branch 1 not taken.
106895579 m_prebuilt->index = innobase_get_index(keynr);
12073
12074
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 106895888 times.
106895888 if (m_prebuilt->index == nullptr) {
12075 log_errlog(WARNING_LEVEL, ER_INNODB_ACTIVE_INDEX_CHANGE_FAILED, keynr);
12076 m_prebuilt->index_usable = false;
12077 return 1;
12078 }
12079
12080
1/2
✓ Branch 0 taken 106895590 times.
✗ Branch 1 not taken.
106895888 m_prebuilt->index_usable = m_prebuilt->index->is_usable(m_prebuilt->trx);
12081
12082
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 106895569 times.
106895590 if (!m_prebuilt->index_usable) {
12083
3/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 9 times.
21 if (m_prebuilt->index->is_corrupted()) {
12084 char table_name[MAX_FULL_NAME_LEN + 1];
12085
12086 12 innobase_format_name(table_name, sizeof table_name,
12087
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 m_prebuilt->index->table->name.m_name);
12088
12089
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (m_prebuilt->index->is_clustered()) {
12090 ut_ad(m_prebuilt->table->is_corrupted());
12091 push_warning_printf(m_user_thd, Sql_condition::SL_WARNING,
12092 HA_ERR_TABLE_CORRUPT,
12093 "InnoDB: Table %s is corrupted.", table_name);
12094 return HA_ERR_TABLE_CORRUPT;
12095 } else {
12096
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 push_warning_printf(m_user_thd, Sql_condition::SL_WARNING,
12097 HA_ERR_INDEX_CORRUPT,
12098 "InnoDB: Index %s for table %s is"
12099 " marked as corrupted",
12100 12 m_prebuilt->index->name(), table_name);
12101
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 my_error(ER_INDEX_CORRUPT, MYF(0), m_prebuilt->index->name());
12102 12 return HA_ERR_INDEX_CORRUPT;
12103 }
12104 } else {
12105
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 push_warning_printf(m_user_thd, Sql_condition::SL_WARNING,
12106 HA_ERR_TABLE_DEF_CHANGED,
12107 "InnoDB: insufficient history for index %u", keynr);
12108 }
12109
12110 /* The caller seems to ignore this. Thus, we must check
12111 this again in row_search_for_mysql(). */
12112 9 return HA_ERR_TABLE_DEF_CHANGED;
12113 }
12114
12115
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 106895387 times.
106895569 ut_a(m_prebuilt->search_tuple != nullptr);
12116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 106895512 times.
106895387 ut_a(m_prebuilt->m_stop_tuple != nullptr);
12117
12118 /* Initialization of search_tuple is not needed for FT index
12119 since FT search returns rank only. In addition engine should
12120 be able to retrieve FTS_DOC_ID column value if necessary. */
12121
2/2
✓ Branch 0 taken 1892 times.
✓ Branch 1 taken 106893620 times.
106895512 if ((m_prebuilt->index->type & DICT_FTS)) {
12122
1/2
✓ Branch 0 taken 128 times.
✗ Branch 1 not taken.
128 if (table->fts_doc_id_field &&
12123 128 bitmap_is_set(table->read_set,
12124
4/4
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 1764 times.
✓ Branch 2 taken 38 times.
✓ Branch 3 taken 1854 times.
2020 table->fts_doc_id_field->field_index()) &&
12125
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 90 times.
128 m_prebuilt->read_just_key) {
12126 38 m_prebuilt->fts_doc_id_in_read_set = true;
12127 }
12128 } else {
12129
1/2
✓ Branch 0 taken 106894009 times.
✗ Branch 1 not taken.
106893620 m_prebuilt->init_search_tuples_types();
12130
12131 /* If it's FTS query and FTS_DOC_ID exists FTS_DOC_ID field is
12132 always added to read_set. */
12133 106894009 m_prebuilt->fts_doc_id_in_read_set =
12134
4/4
✓ Branch 0 taken 966324 times.
✓ Branch 1 taken 105927685 times.
✓ Branch 2 taken 54 times.
✓ Branch 3 taken 966270 times.
106894063 (m_prebuilt->read_just_key && table->fts_doc_id_field &&
12135
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 3 times.
54 m_prebuilt->in_fts_query);
12136 }
12137
12138 /* MySQL changes the active index for a handle also during some
12139 queries, for example SELECT MAX(a), SUM(a) first retrieves the MAX()
12140 and then calculates the sum. Previously we played safe and used
12141 the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary
12142 copying. Starting from MySQL-4.1 we use a more efficient flag here. */
12143
12144
1/2
✓ Branch 0 taken 106895712 times.
✗ Branch 1 not taken.
106895901 build_template(false);
12145
12146 106895712 return 0;
12147 106895735 }
12148
12149 /** Reads the next or previous row from a cursor, which must have previously
12150 been positioned using index_read.
12151 @return 0, HA_ERR_END_OF_FILE, or error number */
12152
12153 368042029 int ha_innobase::general_fetch(
12154 uchar *buf, /*!< in/out: buffer for next row in MySQL
12155 format */
12156 uint direction, /*!< in: ROW_SEL_NEXT or ROW_SEL_PREV */
12157 uint match_mode) /*!< in: 0, ROW_SEL_EXACT, or
12158 ROW_SEL_EXACT_PREFIX */
12159 {
12160
1/2
✓ Branch 0 taken 368042262 times.
✗ Branch 1 not taken.
368042029 DBUG_TRACE;
12161
12162
8/14
✓ Branch 0 taken 368042270 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 365985064 times.
✓ Branch 3 taken 2057206 times.
✓ Branch 4 taken 365985016 times.
✓ Branch 5 taken 2057246 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 365985016 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 368042262 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 368042262 times.
368042262 if (UNIV_UNLIKELY(srv_pass_corrupt_table <= 1 && m_share &&
12163 m_share->ib_table && m_share->ib_table->is_corrupt))
12164 return HA_ERR_CRASHED;
12165
12166 368042262 const trx_t *trx = m_prebuilt->trx;
12167
12168
2/4
✓ Branch 0 taken 368041673 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 368041866 times.
368042262 ut_ad(trx == thd_to_trx(m_user_thd));
12169
12170
1/2
✓ Branch 0 taken 368041839 times.
✗ Branch 1 not taken.
368041866 bool intrinsic = m_prebuilt->table->is_intrinsic();
12171
12172
7/8
✓ Branch 0 taken 350392466 times.
✓ Branch 1 taken 17649373 times.
✓ Branch 2 taken 350391773 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 154 times.
✓ Branch 5 taken 350391619 times.
✓ Branch 6 taken 154 times.
✓ Branch 7 taken 368040992 times.
368041839 if (!intrinsic && TrxInInnoDB::is_aborted(trx)) {
12173
1/2
✓ Branch 0 taken 154 times.
✗ Branch 1 not taken.
154 innobase_rollback(ht, m_user_thd, false);
12174
12175
1/2
✓ Branch 0 taken 154 times.
✗ Branch 1 not taken.
154 return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd);
12176 }
12177
12178
1/2
✓ Branch 0 taken 368041070 times.
✗ Branch 1 not taken.
368040992 auto ret = innobase_srv_conc_enter_innodb(m_prebuilt);
12179
12180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 368041070 times.
368041070 if (ret != DB_SUCCESS) {
12181 return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd);
12182 }
12183
12184
2/2
✓ Branch 0 taken 350391702 times.
✓ Branch 1 taken 17649368 times.
368041070 if (!intrinsic) {
12185
1/2
✓ Branch 0 taken 350391655 times.
✗ Branch 1 not taken.
350391702 ret = row_search_mvcc(buf, PAGE_CUR_UNSUPP, m_prebuilt, match_mode,
12186 direction);
12187
12188 } else {
12189
1/2
✓ Branch 0 taken 17649444 times.
✗ Branch 1 not taken.
17649368 ret = row_search_no_mvcc(buf, PAGE_CUR_UNSUPP, m_prebuilt, match_mode,
12190 direction);
12191 }
12192
12193
1/2
✓ Branch 0 taken 368041673 times.
✗ Branch 1 not taken.
368041099 innobase_srv_conc_exit_innodb(m_prebuilt);
12194
12195 int error;
12196
12197
4/6
✓ Branch 0 taken 346108000 times.
✓ Branch 1 taken 17933623 times.
✓ Branch 2 taken 3999759 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 291 times.
368041673 switch (ret) {
12198 346108000 case DB_SUCCESS:
12199 346108000 error = 0;
12200
2/2
✓ Branch 0 taken 207832383 times.
✓ Branch 1 taken 138275617 times.
346108000 if (m_prebuilt->table->is_system_table) {
12201
1/2
✓ Branch 0 taken 207832373 times.
✗ Branch 1 not taken.
207832374 srv_stats.n_system_rows_read.add(
12202
1/2
✓ Branch 0 taken 207832374 times.
✗ Branch 1 not taken.
207832383 thd_get_thread_id(m_prebuilt->trx->mysql_thd), 1);
12203 } else {
12204
2/4
✓ Branch 0 taken 138275684 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 138275530 times.
✗ Branch 3 not taken.
138275617 srv_stats.n_rows_read.add(thd_get_thread_id(m_prebuilt->trx->mysql_thd),
12205 1);
12206 }
12207 346107903 break;
12208 17933623 case DB_RECORD_NOT_FOUND:
12209 17933623 error = HA_ERR_END_OF_FILE;
12210 17933623 break;
12211 3999759 case DB_END_OF_INDEX:
12212 3999759 error = HA_ERR_END_OF_FILE;
12213 3999759 break;
12214 case DB_TABLESPACE_DELETED:
12215 ib_senderrf(trx->mysql_thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_DISCARDED,
12216 table->s->table_name.str);
12217
12218 error = HA_ERR_NO_SUCH_TABLE;
12219 break;
12220 case DB_TABLESPACE_NOT_FOUND:
12221
12222 ib_senderrf(trx->mysql_thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_MISSING,
12223 table->s->table_name.str);
12224
12225 error = HA_ERR_TABLESPACE_MISSING;
12226 break;
12227 291 default:
12228
1/2
✓ Branch 0 taken 102 times.
✗ Branch 1 not taken.
291 error = convert_error_code_to_mysql(ret, m_prebuilt->table->flags,
12229 m_user_thd);
12230
12231 102 break;
12232 }
12233
12234 368041387 return error;
12235 368041541 }
12236
12237 /** Reads the next row from a cursor, which must have previously been
12238 positioned using index_read.
12239 @return 0, HA_ERR_END_OF_FILE, or error number */
12240
12241 23118236 int ha_innobase::index_next(uchar *buf) /*!< in/out: buffer for next row in
12242 MySQL format */
12243 {
12244 23118236 ha_statistic_increment(&System_status_var::ha_read_next_count);
12245
12246 23118237 return (general_fetch(buf, ROW_SEL_NEXT, 0));
12247 }
12248
12249 /** Reads the next row matching to the key value given as the parameter.
12250 @return 0, HA_ERR_END_OF_FILE, or error number */
12251
12252 102170034 int ha_innobase::index_next_same(uchar *buf, /*!< in/out: buffer for the row */
12253 const uchar *, /*!< in: key value */
12254 uint) /*!< in: key value length */
12255 {
12256 102170034 ha_statistic_increment(&System_status_var::ha_read_next_count);
12257
12258 102170062 return (general_fetch(buf, ROW_SEL_NEXT, m_last_match_mode));
12259 }
12260
12261 /** Reads the previous row from a cursor, which must have previously been
12262 positioned using index_read.
12263 @return 0, HA_ERR_END_OF_FILE, or error number */
12264
12265 19280 int ha_innobase::index_prev(
12266 uchar *buf) /*!< in/out: buffer for previous row in MySQL format */
12267 {
12268 19280 ha_statistic_increment(&System_status_var::ha_read_prev_count);
12269
12270 19280 return (general_fetch(buf, ROW_SEL_PREV, 0));
12271 }
12272
12273 /** Positions a cursor on the first record in an index and reads the
12274 corresponding row to buf.
12275 @return 0, HA_ERR_END_OF_FILE, or error code */
12276
12277 4831213 int ha_innobase::index_first(uchar *buf) /*!< in/out: buffer for the row */
12278 {
12279
1/2
✓ Branch 0 taken 4831346 times.
✗ Branch 1 not taken.
4831213 DBUG_TRACE;
12280
12281
1/2
✓ Branch 0 taken 4831352 times.
✗ Branch 1 not taken.
4831346 ha_statistic_increment(&System_status_var::ha_read_first_count);
12282
12283
1/2
✓ Branch 0 taken 4831342 times.
✗ Branch 1 not taken.
4831352 int error = index_read(buf, nullptr, 0, HA_READ_AFTER_KEY);
12284
12285 /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
12286
12287
2/2
✓ Branch 0 taken 744697 times.
✓ Branch 1 taken 4086645 times.
4831342 if (error == HA_ERR_KEY_NOT_FOUND) {
12288 744697 error = HA_ERR_END_OF_FILE;
12289 }
12290
12291 4831350 return error;
12292 4831342 }
12293
12294 /** Positions a cursor on the last record in an index and reads the
12295 corresponding row to buf.
12296 @return 0, HA_ERR_END_OF_FILE, or error code */
12297
12298 14380 int ha_innobase::index_last(uchar *buf) /*!< in/out: buffer for the row */
12299 {
12300
1/2
✓ Branch 0 taken 14380 times.
✗ Branch 1 not taken.
14380 DBUG_TRACE;
12301
12302
1/2
✓ Branch 0 taken 14380 times.
✗ Branch 1 not taken.
14380 ha_statistic_increment(&System_status_var::ha_read_last_count);
12303
12304
1/2
✓ Branch 0 taken 14380 times.
✗ Branch 1 not taken.
14380 int error = index_read(buf, nullptr, 0, HA_READ_BEFORE_KEY);
12305
12306 /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
12307
12308
2/2
✓ Branch 0 taken 4547 times.
✓ Branch 1 taken 9833 times.
14380 if (error == HA_ERR_KEY_NOT_FOUND) {
12309 4547 error = HA_ERR_END_OF_FILE;
12310 }
12311
12312 14380 return error;
12313 14380 }
12314
12315 199 int ha_innobase::sample_init(void *&scan_ctx, double sampling_percentage,
12316 int sampling_seed,
12317 enum_sampling_method sampling_method,
12318 const bool tablesample) {
12319
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 199 times.
199 ut_ad(table_share->is_missing_primary_key() ==
12320 (bool)m_prebuilt->clust_index_was_generated);
12321
12322
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 199 times.
199 ut_ad(sampling_percentage >= 0.0);
12323
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 199 times.
199 ut_ad(sampling_percentage <= 100.0);
12324
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 199 times.
199 ut_ad(sampling_method == enum_sampling_method::SYSTEM);
12325
12326
2/4
✓ Branch 0 taken 199 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 199 times.
✗ Branch 3 not taken.
199 if (sampling_percentage <= 0.0 || sampling_percentage > 100.0 ||
12327
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 199 times.
199 sampling_method != enum_sampling_method::SYSTEM) {
12328 return 0;
12329 }
12330
12331
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 198 times.
199 if (dict_table_is_discarded(m_prebuilt->table)) {
12332
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 ib_senderrf(ha_thd(), IB_LOG_LEVEL_ERROR, ER_TABLESPACE_DISCARDED,
12333
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 m_prebuilt->table->name.m_name);
12334
12335 1 return HA_ERR_NO_SUCH_TABLE;
12336 }
12337
12338
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
198 int err = change_active_index(table_share->primary_key);
12339
12340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
198 if (err != 0) {
12341 return err;
12342 }
12343
12344 198 trx_t *trx{nullptr};
12345
12346
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
198 if (tablesample) {
12347 update_thd();
12348
12349 trx = m_prebuilt->trx;
12350 trx_start_if_not_started_xa(trx, false, UT_LOCATION_HERE);
12351
12352 if (trx->isolation_level > TRX_ISO_READ_UNCOMMITTED) {
12353 trx_assign_read_view(trx);
12354 }
12355 }
12356
12357 /* Parallel read is not currently supported for sampling. */
12358
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
198 size_t max_threads = Parallel_reader::available_threads(1, false);
12359
12360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
198 if (max_threads == 0) {
12361 return HA_ERR_SAMPLING_INIT_FAILED;
12362 }
12363
12364
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
198 Histogram_sampler *sampler = ut::new_withkey<Histogram_sampler>(
12365 198 UT_NEW_THIS_FILE_PSI_KEY, max_threads, sampling_seed, sampling_percentage,
12366 sampling_method);
12367
12368
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
198 if (sampler == nullptr) {
12369 Parallel_reader::release_threads(max_threads);
12370 return HA_ERR_OUT_OF_MEM;
12371 }
12372
12373 198 scan_ctx = static_cast<void *>(sampler);
12374
12375
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
198 auto index = m_prebuilt->table->first_index();
12376
12377
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
198 auto success = sampler->init(trx, index, m_prebuilt);
12378
12379
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
198 if (!success) {
12380 return (HA_ERR_SAMPLING_INIT_FAILED);
12381 }
12382
12383
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
198 dberr_t db_err = sampler->run();
12384
12385
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
198 if (db_err != DB_SUCCESS) {
12386 return (convert_error_code_to_mysql(db_err, 0, ha_thd()));
12387 }
12388
12389 198 return (0);
12390 }
12391
12392 40909 int ha_innobase::sample_next(void *scan_ctx, uchar *buf) {
12393 40909 dberr_t err = DB_SUCCESS;
12394
12395 40909 Histogram_sampler *sampler = static_cast<Histogram_sampler *>(scan_ctx);
12396
12397 40909 sampler->set(buf);
12398
12399 /** Buffer rows one by one */
12400 40909 err = sampler->buffer_next();
12401
12402
2/2
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 40714 times.
40909 if (err == DB_END_OF_INDEX) {
12403 195 return HA_ERR_END_OF_FILE;
12404 }
12405
12406 40714 return (convert_error_code_to_mysql(err, 0, ha_thd()));
12407 }
12408
12409 198 int ha_innobase::sample_end(void *scan_ctx) {
12410 198 Histogram_sampler *sampler = static_cast<Histogram_sampler *>(scan_ctx);
12411
12412 198 ut::delete_(sampler);
12413
12414 198 return 0;
12415 }
12416
12417 434902 int ha_innobase::read_range_first(const key_range *start_key,
12418 const key_range *end_key, bool eq_range_arg,
12419 bool sorted) {
12420
1/2
✓ Branch 0 taken 434949 times.
✗ Branch 1 not taken.
434902 auto guard = m_prebuilt->get_is_reading_range_guard();
12421
1/2
✓ Branch 0 taken 435060 times.
✗ Branch 1 not taken.
870009 return handler::read_range_first(start_key, end_key, eq_range_arg, sorted);
12422 435060 }
12423
12424 3222057 int ha_innobase::read_range_next() {
12425
1/2
✓ Branch 0 taken 3222057 times.
✗ Branch 1 not taken.
3222057 auto guard = m_prebuilt->get_is_reading_range_guard();
12426
1/2
✓ Branch 0 taken 3222057 times.
✗ Branch 1 not taken.
6444114 return (handler::read_range_next());
12427 3222057 }
12428
12429 /** Initialize a table scan.
12430 @param[in] scan whether this is a second call to rnd_init()
12431 without rnd_end() in between
12432 @return 0 or error number */
12433 4342419 int ha_innobase::rnd_init(bool scan) {
12434
1/2
✓ Branch 0 taken 4342421 times.
✗ Branch 1 not taken.
4342419 DBUG_TRACE;
12435
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4342421 times.
4342421 assert(table_share->is_missing_primary_key() ==
12436 (bool)m_prebuilt->clust_index_was_generated);
12437
12438
1/2
✓ Branch 0 taken 4342420 times.
✗ Branch 1 not taken.
4342421 int err = change_active_index(table_share->primary_key);
12439
12440 /* Don't use semi-consistent read in random row reads (by position).
12441 This means we must disable semi_consistent_read if scan is false */
12442
12443
2/2
✓ Branch 0 taken 590948 times.
✓ Branch 1 taken 3751472 times.
4342420 if (!scan) {
12444 590948 m_prebuilt->row_read_type = ROW_READ_WITH_LOCKS;
12445 }
12446
12447 4342420 m_start_of_scan = true;
12448 4342420 return err;
12449 4342420 }
12450
12451 /** Ends a table scan.
12452 @return 0 or error number */
12453
12454 2217470 int ha_innobase::rnd_end(void) { return (index_end()); }
12455
12456 /** Reads the next row in a table scan (also used to read the FIRST row
12457 in a table scan).
12458 @return 0, HA_ERR_END_OF_FILE, or error number */
12459
12460 244899389 int ha_innobase::rnd_next(uchar *buf) /*!< in/out: returns the row in this
12461 buffer, in MySQL format */
12462 {
12463 int error;
12464
12465
1/2
✓ Branch 0 taken 244899898 times.
✗ Branch 1 not taken.
244899389 DBUG_TRACE;
12466
12467
1/2
✓ Branch 0 taken 244899820 times.
✗ Branch 1 not taken.
244899898 ha_statistic_increment(&System_status_var::ha_read_rnd_next_count);
12468
12469
2/2
✓ Branch 0 taken 3751445 times.
✓ Branch 1 taken 241148375 times.
244899820 if (m_start_of_scan) {
12470
1/2
✓ Branch 0 taken 3751440 times.
✗ Branch 1 not taken.
3751445 error = index_first(buf);
12471
12472
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3751440 times.
3751440 if (error == HA_ERR_KEY_NOT_FOUND) {
12473 error = HA_ERR_END_OF_FILE;
12474 }
12475
12476 3751440 m_start_of_scan = false;
12477 } else {
12478
1/2
✓ Branch 0 taken 241146633 times.
✗ Branch 1 not taken.
241148375 error = general_fetch(buf, ROW_SEL_NEXT, 0);
12479 }
12480
12481 244900075 return error;
12482 244898073 }
12483
12484 /** Fetches a row from the table based on a row reference.
12485 @return 0, HA_ERR_KEY_NOT_FOUND, or error code */
12486
12487 8601858 int ha_innobase::rnd_pos(
12488 uchar *buf, /*!< in/out: buffer for the row */
12489 uchar *pos) /*!< in: primary key value of the row in the
12490 MySQL format, or the row id if the clustered
12491 index was internally generated by InnoDB; the
12492 length of data in pos has to be ref_length */
12493 {
12494
1/2
✓ Branch 0 taken 8601864 times.
✗ Branch 1 not taken.
8601858 DBUG_TRACE;
12495
1/2
✓ Branch 0 taken 8601863 times.
✗ Branch 1 not taken.
8601864 DBUG_DUMP("key", pos, ref_length);
12496
12497
1/2
✓ Branch 0 taken 8601863 times.
✗ Branch 1 not taken.
8601863 ha_statistic_increment(&System_status_var::ha_read_rnd_count);
12498
12499
3/6
✓ Branch 0 taken 8601864 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8601863 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8601864 times.
8601863 ut_a(m_prebuilt->trx == thd_to_trx(ha_thd()));
12500
12501 /* Note that we assume the length of the row reference is fixed
12502 for the table, and it is == ref_length */
12503
12504
1/2
✓ Branch 0 taken 8601863 times.
✗ Branch 1 not taken.
8601864 int error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT);
12505
12506
2/2
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 8601770 times.
8601863 if (error != 0) {
12507
3/8
✓ Branch 0 taken 93 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 93 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 93 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
93 DBUG_PRINT("error", ("Got error: %d", error));
12508 } else {
12509 8601770 m_start_of_scan = false;
12510 }
12511
12512 8601864 return error;
12513 8601863 }
12514
12515 /** Initialize FT index scan
12516 @return 0 or error number */
12517
12518 1918 int ha_innobase::ft_init() {
12519
1/2
✓ Branch 0 taken 1918 times.
✗ Branch 1 not taken.
1918 DBUG_TRACE;
12520
12521
2/4
✓ Branch 0 taken 1918 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1918 times.
✗ Branch 3 not taken.
1918 trx_t *trx = check_trx_exists(ha_thd());
12522
12523 /* FTS queries are not treated as autocommit non-locking selects.
12524 This is because the FTS implementation can acquire locks behind
12525 the scenes. This has not been verified but it is safer to treat
12526 them as regular read only transactions for now. */
12527
12528
3/4
✓ Branch 0 taken 1918 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1690 times.
✓ Branch 3 taken 228 times.
1918 if (!trx_is_started(trx)) {
12529 1690 ++trx->will_lock;
12530 }
12531
12532
1/2
✓ Branch 0 taken 1918 times.
✗ Branch 1 not taken.
3836 return rnd_init(false);
12533 1918 }
12534
12535 /** Initialize FT index scan
12536 @return FT_INFO structure if successful or NULL */
12537
12538 2295 FT_INFO *ha_innobase::ft_init_ext(uint flags, /* in: */
12539 uint keynr, /* in: */
12540 String *key) /* in: */
12541 {
12542 2295 NEW_FT_INFO *fts_hdl = nullptr;
12543 dict_index_t *index;
12544 fts_result_t *result;
12545 char buf_tmp[8192];
12546 ulint buf_tmp_used;
12547 uint num_errors;
12548 2295 ulint query_len = key->length();
12549 2295 const CHARSET_INFO *char_set = key->charset();
12550 2295 const char *query = key->ptr();
12551
12552
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 2257 times.
2295 if (fts_enable_diag_print) {
12553 {
12554
1/2
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
38 ib::info out(ER_IB_MSG_1220);
12555
3/6
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 38 times.
✗ Branch 5 not taken.
38 out << "keynr=" << keynr << ", '";
12556
1/2
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
38 out.write(key->ptr(), key->length());
12557 38 }
12558
12559
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 6 times.
38 if (flags & FT_BOOL) {
12560
2/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
32 ib::info(ER_IB_MSG_562) << "BOOL search";
12561 } else {
12562
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 ib::info(ER_IB_MSG_563) << "NL search";
12563 }
12564 }
12565
12566 /* FIXME: utf32 and utf16 are not compatible with some
12567 string function used. So to convert them to uft8 before
12568 we proceed. */
12569
1/2
✓ Branch 0 taken 2295 times.
✗ Branch 1 not taken.
2295 if (strcmp(char_set->csname, "utf32") == 0 ||
12570
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2295 times.
2295 strcmp(char_set->csname, "utf16") == 0) {
12571 buf_tmp_used = innobase_convert_string(
12572 buf_tmp, sizeof(buf_tmp) - 1, &my_charset_utf8_general_ci, query,
12573 query_len, (CHARSET_INFO *)char_set, &num_errors);
12574
12575 buf_tmp[buf_tmp_used] = 0;
12576 query = buf_tmp;
12577 query_len = buf_tmp_used;
12578 }
12579
12580 2295 trx_t *trx = m_prebuilt->trx;
12581
12582
1/2
✓ Branch 0 taken 2295 times.
✗ Branch 1 not taken.
2295 TrxInInnoDB trx_in_innodb(trx);
12583
12584
2/4
✓ Branch 0 taken 2295 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2295 times.
2295 if (trx_in_innodb.is_aborted()) {
12585 innobase_rollback(ht, m_user_thd, false);
12586
12587 int err;
12588 err = convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd);
12589
12590 my_error(err, MYF(0));
12591
12592 return (nullptr);
12593 }
12594
12595 /* FTS queries are not treated as autocommit non-locking selects.
12596 This is because the FTS implementation can acquire locks behind
12597 the scenes. This has not been verified but it is safer to treat
12598 them as regular read only transactions for now. */
12599
12600
3/4
✓ Branch 0 taken 2295 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2123 times.
✓ Branch 3 taken 172 times.
2295 if (!trx_is_started(trx)) {
12601 2123 ++trx->will_lock;
12602 }
12603
12604 2295 dict_table_t *ft_table = m_prebuilt->table;
12605
12606 /* Table does not have an FTS index */
12607
3/6
✓ Branch 0 taken 2295 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2295 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2295 times.
2295 if (!ft_table->fts || ib_vector_is_empty(ft_table->fts->indexes)) {
12608 my_error(ER_TABLE_HAS_NO_FT, MYF(0));
12609 return (nullptr);
12610 }
12611
12612 /* If tablespace is discarded, we should return here */
12613
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2295 times.
2295 if (dict_table_is_discarded(ft_table)) {
12614 my_error(ER_NO_SUCH_TABLE, MYF(0), table->s->db.str,
12615 table->s->table_name.str);
12616 return (nullptr);
12617 }
12618
12619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2295 times.
2295 if (keynr == NO_SUCH_KEY) {
12620 /* FIXME: Investigate the NO_SUCH_KEY usage */
12621 index = reinterpret_cast<dict_index_t *>(
12622 ib_vector_getp(ft_table->fts->indexes, 0));
12623 } else {
12624
1/2
✓ Branch 0 taken 2295 times.
✗ Branch 1 not taken.
2295 index = innobase_get_index(keynr);
12625 }
12626
12627
3/4
✓ Branch 0 taken 2295 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2294 times.
2295 if (index == nullptr || index->type != DICT_FTS) {
12628
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_TABLE_HAS_NO_FT, MYF(0));
12629 1 return (nullptr);
12630 }
12631
12632
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 2241 times.
2294 if (!(ft_table->fts->fts_status & ADDED_TABLE_SYNCED)) {
12633
1/2
✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
53 fts_init_index(ft_table, false);
12634
12635 53 ft_table->fts->fts_status |= ADDED_TABLE_SYNCED;
12636 }
12637
12638 2294 const byte *q = reinterpret_cast<const byte *>(const_cast<char *>(query));
12639
12640 4588 dberr_t error = fts_query(trx, index, flags, q, query_len, &result,
12641
1/2
✓ Branch 0 taken 2294 times.
✗ Branch 1 not taken.
2294 m_prebuilt->m_fts_limit);
12642
12643
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2288 times.
2294 if (error != DB_SUCCESS) {
12644
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 my_error(convert_error_code_to_mysql(error, 0, nullptr), MYF(0));
12645 6 return (nullptr);
12646 }
12647
12648 /* Allocate FTS handler, and instantiate it before return */
12649 fts_hdl = reinterpret_cast<NEW_FT_INFO *>(
12650
1/2
✓ Branch 0 taken 2288 times.
✗ Branch 1 not taken.
2288 my_malloc(PSI_INSTRUMENT_ME, sizeof(NEW_FT_INFO), MYF(0)));
12651
12652 2288 fts_hdl->please = const_cast<_ft_vft *>(&ft_vft_result);
12653 2288 fts_hdl->could_you = const_cast<_ft_vft_ext *>(&ft_vft_ext_result);
12654 2288 fts_hdl->ft_prebuilt = m_prebuilt;
12655 2288 fts_hdl->ft_result = result;
12656
12657 /* FIXME: Re-evaluate the condition when Bug 14469540 is resolved */
12658 2288 m_prebuilt->in_fts_query = true;
12659
12660 2288 return (reinterpret_cast<FT_INFO *>(fts_hdl));
12661 2295 }
12662
12663 /** Initialize FT index scan
12664 @return FT_INFO structure if successful or NULL */
12665
12666 2295 FT_INFO *ha_innobase::ft_init_ext_with_hints(uint keynr, /* in: key num */
12667 String *key, /* in: key */
12668 Ft_hints *hints) /* in: hints */
12669 {
12670 /* TODO Implement function properly working with FT hint. */
12671
2/2
✓ Branch 0 taken 1275 times.
✓ Branch 1 taken 1020 times.
2295 if (hints->get_flags() & FT_NO_RANKING) {
12672 1275 m_prebuilt->m_fts_limit = hints->get_limit();
12673 } else {
12674 1020 m_prebuilt->m_fts_limit = ULONG_UNDEFINED;
12675 }
12676
12677 2295 return (ft_init_ext(hints->get_flags(), keynr, key));
12678 }
12679
12680 /** Set up search tuple for a query through FTS_DOC_ID_INDEX on
12681 supplied Doc ID. This is used by MySQL to retrieve the documents
12682 once the search result (Doc IDs) is available */
12683 36648 static void innobase_fts_create_doc_id_key(
12684 dtuple_t *tuple, /* in/out: m_prebuilt->search_tuple */
12685 const dict_index_t *index, /* in: index (FTS_DOC_ID_INDEX) */
12686 doc_id_t *doc_id) /* in/out: doc id to search, value
12687 could be changed to storage format
12688 used for search. */
12689 {
12690 doc_id_t temp_doc_id;
12691
1/2
✓ Branch 0 taken 36648 times.
✗ Branch 1 not taken.
36648 dfield_t *dfield = dtuple_get_nth_field(tuple, 0);
12692
12693
2/4
✓ Branch 0 taken 36648 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 36648 times.
36648 ut_a(dict_index_get_n_unique(index) == 1);
12694
12695
1/2
✓ Branch 0 taken 36648 times.
✗ Branch 1 not taken.
36648 dtuple_set_n_fields(tuple, index->n_fields);
12696
1/2
✓ Branch 0 taken 36648 times.
✗ Branch 1 not taken.
36648 dict_index_copy_types(tuple, index, index->n_fields);
12697
12698 #ifdef UNIV_DEBUG
12699 /* The unique Doc ID field should be an eight-bytes integer */
12700
1/2
✓ Branch 0 taken 36648 times.
✗ Branch 1 not taken.
36648 dict_field_t *field = index->get_field(0);
12701
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36648 times.
36648 ut_a(field->col->mtype == DATA_INT);
12702
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36648 times.
36648 ut_ad(sizeof(*doc_id) == field->fixed_len);
12703
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36648 times.
36648 ut_ad(!strcmp(index->name, FTS_DOC_ID_INDEX_NAME));
12704 #endif /* UNIV_DEBUG */
12705
12706 /* Convert to storage byte order */
12707
1/2
✓ Branch 0 taken 36648 times.
✗ Branch 1 not taken.
36648 mach_write_to_8(reinterpret_cast<byte *>(&temp_doc_id), *doc_id);
12708 36648 *doc_id = temp_doc_id;
12709
1/2
✓ Branch 0 taken 36648 times.
✗ Branch 1 not taken.
36648 dfield_set_data(dfield, doc_id, sizeof(*doc_id));
12710
12711
1/2
✓ Branch 0 taken 36648 times.
✗ Branch 1 not taken.
36648 dtuple_set_n_fields_cmp(tuple, 1);
12712
12713
2/2
✓ Branch 0 taken 36384 times.
✓ Branch 1 taken 36648 times.
73032 for (ulint i = 1; i < index->n_fields; i++) {
12714
1/2
✓ Branch 0 taken 36384 times.
✗ Branch 1 not taken.
36384 dfield = dtuple_get_nth_field(tuple, i);
12715
1/2
✓ Branch 0 taken 36384 times.
✗ Branch 1 not taken.
36384 dfield_set_null(dfield);
12716 }
12717 36648 }
12718
12719 /** Fetch next result from the FT result set
12720 @return error code */
12721
12722 38636 int ha_innobase::ft_read(uchar *buf) /*!< in/out: buf contain result row */
12723 {
12724
1/2
✓ Branch 0 taken 38636 times.
✗ Branch 1 not taken.
38636 TrxInInnoDB trx_in_innodb(m_prebuilt->trx);
12725
12726
2/4
✓ Branch 0 taken 38636 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 38636 times.
38636 if (trx_in_innodb.is_aborted()) {
12727 innobase_rollback(ht, m_user_thd, false);
12728
12729 return (convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd));
12730 }
12731
12732 row_prebuilt_t *ft_prebuilt;
12733
12734 38636 ft_prebuilt = reinterpret_cast<NEW_FT_INFO *>(ft_handler)->ft_prebuilt;
12735
12736
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38636 times.
38636 ut_a(ft_prebuilt == m_prebuilt);
12737
12738 fts_result_t *result;
12739
12740 38636 result = reinterpret_cast<NEW_FT_INFO *>(ft_handler)->ft_result;
12741
12742
2/2
✓ Branch 0 taken 1907 times.
✓ Branch 1 taken 36729 times.
38636 if (result->current == nullptr) {
12743 /* This is the case where the FTS query did not
12744 contain and matching documents. */
12745
2/2
✓ Branch 0 taken 1416 times.
✓ Branch 1 taken 491 times.
1907 if (result->rankings_by_id != nullptr) {
12746 /* Now that we have the complete result, we
12747 need to sort the document ids on their rank
12748 calculation. */
12749
12750
1/2
✓ Branch 0 taken 1416 times.
✗ Branch 1 not taken.
1416 fts_query_sort_result_on_rank(result);
12751
12752 1416 result->current =
12753
1/2
✓ Branch 0 taken 1416 times.
✗ Branch 1 not taken.
1416 const_cast<ib_rbt_node_t *>(rbt_first(result->rankings_by_rank));
12754 } else {
12755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 491 times.
491 ut_a(result->current == nullptr);
12756 }
12757 } else {
12758 36729 result->current = const_cast<ib_rbt_node_t *>(
12759
1/2
✓ Branch 0 taken 36729 times.
✗ Branch 1 not taken.
36729 rbt_next(result->rankings_by_rank, result->current));
12760 }
12761
12762 38636 next_record:
12763
12764
2/2
✓ Branch 0 taken 36782 times.
✓ Branch 1 taken 1858 times.
38640 if (result->current != nullptr) {
12765 doc_id_t search_doc_id;
12766 36782 dtuple_t *tuple = m_prebuilt->search_tuple;
12767
12768 /* If we only need information from result we can return
12769 without fetching the table row */
12770
2/2
✓ Branch 0 taken 134 times.
✓ Branch 1 taken 36648 times.
36782 if (ft_prebuilt->read_just_key) {
12771 134 const fts_ranking_t *ranking = rbt_value(fts_ranking_t, result->current);
12772 134 m_prebuilt->fts_doc_id = ranking->doc_id;
12773
1/2
✓ Branch 0 taken 134 times.
✗ Branch 1 not taken.
134 if (m_prebuilt->fts_doc_id_in_read_set) {
12774
1/2
✓ Branch 0 taken 134 times.
✗ Branch 1 not taken.
134 innobase_fts_store_docid(table, ranking->doc_id);
12775 }
12776 36778 return (0);
12777 }
12778
12779 dict_index_t *index;
12780
12781 36648 index = m_prebuilt->table->fts_doc_id_index;
12782
12783 /* Must find the index */
12784
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36648 times.
36648 ut_a(index != nullptr);
12785
12786 /* Switch to the FTS doc id index */
12787 36648 m_prebuilt->index = index;
12788
12789 36648 fts_ranking_t *ranking = rbt_value(fts_ranking_t, result->current);
12790
12791 36648 search_doc_id = ranking->doc_id;
12792
12793 /* We pass a pointer of search_doc_id because it will be
12794 converted to storage byte order used in the search
12795 tuple. */
12796
1/2
✓ Branch 0 taken 36648 times.
✗ Branch 1 not taken.
36648 innobase_fts_create_doc_id_key(tuple, index, &search_doc_id);
12797
12798
1/2
✓ Branch 0 taken 36648 times.
✗ Branch 1 not taken.
36648 auto ret = innobase_srv_conc_enter_innodb(m_prebuilt);
12799
12800
1/2
✓ Branch 0 taken 36648 times.
✗ Branch 1 not taken.
36648 if (ret == DB_SUCCESS) {
12801
1/2
✓ Branch 0 taken 36648 times.
✗ Branch 1 not taken.
36648 ret = row_search_for_mysql((byte *)buf, PAGE_CUR_GE, m_prebuilt,
12802 ROW_SEL_EXACT, 0);
12803
1/2
✓ Branch 0 taken 36648 times.
✗ Branch 1 not taken.
36648 innobase_srv_conc_exit_innodb(m_prebuilt);
12804 }
12805
12806 int error;
12807
12808
6/14
✓ Branch 0 taken 36648 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36648 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 36648 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 36648 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 36648 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 36648 times.
36648 if (UNIV_UNLIKELY(srv_pass_corrupt_table <= 1 && m_share &&
12809 m_share->ib_table && m_share->ib_table->is_corrupt)) {
12810 return (HA_ERR_CRASHED);
12811 }
12812
12813
2/6
✓ Branch 0 taken 36632 times.
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
36648 switch (ret) {
12814 36632 case DB_SUCCESS:
12815 36632 error = 0;
12816 36632 break;
12817 16 case DB_RECORD_NOT_FOUND:
12818 16 result->current = const_cast<ib_rbt_node_t *>(
12819
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 rbt_next(result->rankings_by_rank, result->current));
12820
12821
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
16 if (!result->current) {
12822 /* exhaust the result set, should return
12823 HA_ERR_END_OF_FILE just like
12824 ha_innobase::general_fetch() and/or
12825 ha_innobase::index_first() etc. */
12826 12 error = HA_ERR_END_OF_FILE;
12827 } else {
12828 4 goto next_record;
12829 }
12830 12 break;
12831 case DB_END_OF_INDEX:
12832 error = HA_ERR_END_OF_FILE;
12833 break;
12834 case DB_TABLESPACE_DELETED:
12835
12836 ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR,
12837 ER_TABLESPACE_DISCARDED, table->s->table_name.str);
12838
12839 error = HA_ERR_NO_SUCH_TABLE;
12840 break;
12841 case DB_TABLESPACE_NOT_FOUND:
12842
12843 ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR,
12844 ER_TABLESPACE_MISSING, table->s->table_name.str);
12845
12846 error = HA_ERR_TABLESPACE_MISSING;
12847 break;
12848 default:
12849 error = convert_error_code_to_mysql(ret, 0, m_user_thd);
12850
12851 break;
12852 }
12853
12854 36644 return (error);
12855 }
12856
12857 1858 return (HA_ERR_END_OF_FILE);
12858 38636 }
12859
12860 /*************************************************************************
12861 */
12862
12863 void ha_innobase::ft_end() {
12864 ib::info(ER_IB_MSG_564) << "ft_end()";
12865
12866 rnd_end();
12867 }
12868
12869 #ifdef WITH_WSREP
12870 dict_index_t *wsrep_dict_foreign_find_index(dict_table_t *table,
12871 const char **col_names,
12872 const char **columns, ulint n_cols,
12873 dict_index_t *types_idx,
12874 bool check_charsets,
12875 ulint check_null);
12876
12877 inline const char *wsrep_key_type_to_str(Wsrep_service_key_type type) {
12878 switch (type) {
12879 case WSREP_SERVICE_KEY_SHARED:
12880 return "shared";
12881 case WSREP_SERVICE_KEY_REFERENCE:
12882 return "reference";
12883 case WSREP_SERVICE_KEY_UPDATE:
12884 return "update";
12885 case WSREP_SERVICE_KEY_EXCLUSIVE:
12886 return "exclusive";
12887 };
12888 return "unknown";
12889 }
12890
12891 319745 extern dberr_t wsrep_append_foreign_key(
12892 trx_t *trx, /*!< in: trx */
12893 dict_foreign_t *foreign, /*!< in: foreign key constraint */
12894 const rec_t *rec, /*!< in: clustered index record */
12895 dict_index_t *index, /*!< in: clustered index */
12896 bool referenced, /*!< in: is check for referenced table */
12897 Wsrep_service_key_type key_type) /*!< in: access type of this key
12898 (shared, exclusive, reference...) */
12899 {
12900 319745 THD *thd = (THD *)trx->mysql_thd;
12901 319745 int rcode = 0;
12902 319745 char cache_key[513] = {'\0'};
12903 int cache_key_len;
12904
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 319745 times.
319745 ut_a(trx);
12905
12906
3/4
✓ Branch 0 taken 319745 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 305643 times.
✓ Branch 3 taken 14102 times.
319745 if (!wsrep_do_replication(thd)) {
12907 305643 return DB_SUCCESS;
12908 }
12909
12910
2/4
✓ Branch 0 taken 14102 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14102 times.
✗ Branch 3 not taken.
14102 if (!thd || !foreign ||
12911
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 14102 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
14102 (!foreign->referenced_table && !foreign->foreign_table)) {
12912 WSREP_INFO("FK: %s missing in: %s",
12913 (!thd) ? "thread"
12914 : ((!foreign) ? "constraint"
12915 : ((!foreign->referenced_table)
12916 ? "referenced table"
12917 : "foreign table")),
12918 (thd && wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void");
12919 return DB_ERROR;
12920 }
12921
12922
3/4
✓ Branch 0 taken 4030 times.
✓ Branch 1 taken 10072 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14102 times.
14102 if (!((referenced) ? foreign->referenced_table : foreign->foreign_table)) {
12923 WSREP_DEBUG("pulling %s table into cache",
12924 (referenced) ? "referenced" : "foreign");
12925 mutex_enter(&(dict_sys->mutex));
12926 if (referenced) {
12927 foreign->referenced_table =
12928 dict_table_get_low(foreign->referenced_table_name_lookup);
12929 if (foreign->referenced_table) {
12930 foreign->referenced_index = wsrep_dict_foreign_find_index(
12931 foreign->referenced_table, NULL, foreign->referenced_col_names,
12932 foreign->n_fields, foreign->foreign_index, true, false);
12933 }
12934 } else {
12935 foreign->foreign_table =
12936 dict_table_get_low(foreign->foreign_table_name_lookup);
12937 if (foreign->foreign_table) {
12938 foreign->foreign_index = wsrep_dict_foreign_find_index(
12939 foreign->foreign_table, NULL, foreign->foreign_col_names,
12940 foreign->n_fields, foreign->referenced_index, true, false);
12941 }
12942 }
12943 mutex_exit(&(dict_sys->mutex));
12944 }
12945
12946
3/4
✓ Branch 0 taken 4030 times.
✓ Branch 1 taken 10072 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14102 times.
14102 if (!((referenced) ? foreign->referenced_table : foreign->foreign_table)) {
12947 WSREP_WARN(
12948 "FK: %s missing in query: %s",
12949 (!foreign->referenced_table) ? "referenced table" : "foreign table",
12950 (wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void");
12951 return DB_ERROR;
12952 }
12953 14102 byte key[WSREP_MAX_SUPPORTED_KEY_LENGTH + 1] = {'\0'};
12954 14102 ulint len = WSREP_MAX_SUPPORTED_KEY_LENGTH;
12955
12956
2/2
✓ Branch 0 taken 4030 times.
✓ Branch 1 taken 10072 times.
14102 dict_index_t *idx_target = (referenced) ? foreign->referenced_index : index;
12957 14102 dict_index_t *idx =
12958
2/2
✓ Branch 0 taken 4030 times.
✓ Branch 1 taken 10072 times.
14102 (referenced) ? UT_LIST_GET_FIRST(foreign->referenced_table->indexes)
12959 10072 : UT_LIST_GET_FIRST(foreign->foreign_table->indexes);
12960 14102 int i = 0;
12961
3/4
✓ Branch 0 taken 14126 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 14102 times.
14126 while (idx != NULL && idx != idx_target) {
12962
3/4
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 17 times.
24 if (innobase_strcasecmp(idx->name, innobase_index_reserve_name) != 0) {
12963 7 i++;
12964 }
12965 24 idx = UT_LIST_GET_NEXT(indexes, idx);
12966 }
12967
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14102 times.
14102 ut_a(idx);
12968 14102 key[0] = (char)i;
12969
12970
1/2
✓ Branch 0 taken 14102 times.
✗ Branch 1 not taken.
14102 rcode = wsrep_rec_get_foreign_key(&key[1], &len, rec, index, idx,
12971 wsrep_protocol_version > 1);
12972
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14102 times.
14102 if (rcode != DB_SUCCESS) {
12973 WSREP_ERROR(
12974 "FK key set failed: %d (%d %s), index: %s %s, %s", rcode, referenced,
12975 wsrep_key_type_to_str(key_type),
12976 (index && index->name) ? (const char *)(index->name) : "void index",
12977 (index && index->table_name) ? (index->table_name) : "void table",
12978 wsrep_thd_query(thd));
12979 return DB_ERROR;
12980 }
12981
2/2
✓ Branch 0 taken 4030 times.
✓ Branch 1 taken 10072 times.
28204 strncpy(cache_key,
12982
1/2
✓ Branch 0 taken 14102 times.
✗ Branch 1 not taken.
14102 (wsrep_protocol_version > 1)
12983 4030 ? ((referenced) ? foreign->referenced_table->name.m_name
12984 10072 : foreign->foreign_table->name.m_name)
12985 : foreign->foreign_table->name.m_name,
12986 sizeof(cache_key) - 1);
12987 14102 cache_key_len = strlen(cache_key);
12988 #ifdef WSREP_DEBUG_PRINT
12989 ulint j;
12990 fprintf(stderr, "FK parent key, table: %s %s len: %lu ", cache_key,
12991 wsrep_key_type_to_str(key_type), len + 1);
12992 for (j = 0; j < len + 1; j++) {
12993 fprintf(stderr, " %hhX, ", key[j]);
12994 }
12995 fprintf(stderr, "\n");
12996 #endif /* WSREP_DEBUG_PRINT */
12997 14102 char *p = strchr(cache_key, '/');
12998
1/2
✓ Branch 0 taken 14102 times.
✗ Branch 1 not taken.
14102 if (p) {
12999 14102 *p = '\0';
13000 } else {
13001 WSREP_WARN("unexpected foreign key table %s %s",
13002 foreign->referenced_table->name.m_name,
13003 foreign->foreign_table->name.m_name);
13004 }
13005
13006 wsrep_buf_t wkey_part[3];
13007 14102 wsrep_key_t wkey = {wkey_part, 3};
13008
2/4
✓ Branch 0 taken 14102 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 14102 times.
14102 if (!wsrep_prepare_key_for_innodb((const uchar *)cache_key, cache_key_len + 1,
13009 (const uchar *)key, len + 1, wkey_part,
13010 &wkey.key_parts_num)) {
13011 WSREP_WARN("key prepare failed for cascaded FK: %s",
13012 (wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void");
13013 return DB_ERROR;
13014 }
13015
1/2
✓ Branch 0 taken 14102 times.
✗ Branch 1 not taken.
14102 rcode = wsrep_thd_append_key(thd, &wkey, 1, key_type);
13016
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14102 times.
14102 if (rcode) {
13017 DBUG_PRINT("wsrep", ("row key failed: %d", rcode));
13018 WSREP_ERROR("Appending cascaded fk row key failed: %s, %d",
13019 (wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void", rcode);
13020 return DB_ERROR;
13021 }
13022
13023 14102 return DB_SUCCESS;
13024 }
13025
13026 3832404 static int wsrep_append_key(
13027 THD *thd, trx_t *trx, TABLE_SHARE *table_share, const char *key,
13028 uint16_t key_len,
13029 Wsrep_service_key_type key_type /*!< in: access type of this key
13030 (shared, exclusive, semi...) */
13031 ) {
13032
1/2
✓ Branch 0 taken 3832404 times.
✗ Branch 1 not taken.
3832404 DBUG_ENTER("wsrep_append_key");
13033 #ifdef WSREP_DEBUG_PRINT
13034 if (wsrep_debug) {
13035 fprintf(stderr, "%s conn %lu, trx %llu, keylen %d, table %s\n SQL: %s ",
13036 wsrep_key_type_to_str(key_type), wsrep_thd_thread_id(thd),
13037 (long long)trx->id, key_len, table_share->table_name.str,
13038 wsrep_thd_query(thd));
13039 for (int i = 0; i < key_len; i++) {
13040 fprintf(stderr, "%hhX, ", key[i]);
13041 }
13042 fprintf(stderr, "\n");
13043 }
13044 #endif /* WSREP_DEBUG_PRINT */
13045 wsrep_buf_t wkey_part[3];
13046 3832404 wsrep_key_t wkey = {wkey_part, 3};
13047
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3832404 times.
3832404 if (!wsrep_prepare_key_for_innodb(
13048
1/2
✓ Branch 0 taken 3832404 times.
✗ Branch 1 not taken.
3832404 (const uchar *)table_share->table_cache_key.str,
13049 table_share->table_cache_key.length, (const uchar *)key, key_len,
13050 wkey_part, &wkey.key_parts_num)) {
13051 WSREP_WARN("key prepare failed for: %s",
13052 (wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void");
13053 DBUG_RETURN(-1);
13054 }
13055
13056
1/2
✓ Branch 0 taken 3832404 times.
✗ Branch 1 not taken.
3832404 int rcode = wsrep_thd_append_key(thd, &wkey, 1, key_type);
13057
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3832403 times.
3832404 if (rcode) {
13058
3/8
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1 DBUG_PRINT("wsrep", ("row key failed: %d", rcode));
13059
13/28
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
1 WSREP_WARN("Appending row key failed: %s, %d",
13060 (wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void", rcode);
13061
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 DBUG_RETURN(-1);
13062 }
13063
1/2
✓ Branch 0 taken 3832403 times.
✗ Branch 1 not taken.
3832403 DBUG_RETURN(0);
13064 }
13065
13066 extern int compute_md5_hash(char *digest, const char *buf, int len);
13067 #define MD5_HASH compute_md5_hash
13068
13069 15122 bool wsrep_is_FK_index(dict_table_t *table, dict_index_t *index) {
13070 15122 const dict_foreign_set *fks = &table->referenced_set;
13071
13072 /* Check for all FK references from other tables to the index. */
13073
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 15115 times.
15136 for (dict_foreign_set::const_iterator it = fks->begin(); it != fks->end();
13074 14 ++it) {
13075 21 dict_foreign_t *foreign = *it;
13076
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 14 times.
21 if (foreign->referenced_index == index) {
13077
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 ut_ad(table == foreign->referenced_table);
13078 7 return true;
13079 }
13080 }
13081 15115 return false;
13082 }
13083
13084 4343913 int ha_innobase::wsrep_append_keys(
13085 THD *thd, /*!< in: thread handler */
13086 Wsrep_service_key_type key_type, /*!< in: access type of this key
13087 (shared, exclusive, reference...) */
13088 const uchar *record0, /* in: row in MySQL format */
13089 const uchar *record1) /* in: row in MySQL format */
13090 {
13091 /* Sanity check: newly inserted records should always be passed with
13092 EXCLUSIVE key type, all the rest are expected to carry a pre-image
13093 */
13094
4/6
✓ Branch 0 taken 3723050 times.
✓ Branch 1 taken 620863 times.
✓ Branch 2 taken 3723050 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4343913 times.
4343913 ut_a(record1 != NULL || key_type == WSREP_SERVICE_KEY_EXCLUSIVE);
13095
13096 int rcode;
13097
1/2
✓ Branch 0 taken 4343913 times.
✗ Branch 1 not taken.
4343913 DBUG_ENTER("wsrep_append_keys");
13098
13099 4343913 bool key_appended = false;
13100
1/2
✓ Branch 0 taken 4343913 times.
✗ Branch 1 not taken.
4343913 trx_t *trx = thd_to_trx(thd);
13101
13102 #ifdef WSREP_DEBUG_PRINT
13103 fprintf(stderr, "%s conn %lu, trx " TRX_ID_FMT ", table %s\nSQL: %s\n",
13104 wsrep_key_type_to_str(key_type), thd_get_thread_id(thd), trx->id,
13105 table_share->table_name.str, wsrep_thd_query(thd));
13106 #endif /* WSREP_DEBUG_PRINT */
13107
13108
3/4
✓ Branch 0 taken 4343913 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 521167 times.
✓ Branch 3 taken 3822746 times.
4343913 if (table_share && table_share->tmp_table != NO_TMP_TABLE) {
13109
16/32
✓ Branch 0 taken 13123 times.
✓ Branch 1 taken 508044 times.
✓ Branch 2 taken 13123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13123 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 13123 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 13123 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 13123 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 13123 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 13123 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 13123 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 13123 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 13123 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 13123 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 13123 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 13123 times.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✓ Branch 29 taken 13123 times.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
521167 WSREP_DEBUG(
13110 "Skip appending keys to write-set for"
13111 " temporary-tables DML (THD: %u tmp: %d SQL: %s)",
13112 wsrep_thd_thread_id(thd), table_share->tmp_table,
13113 (wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void");
13114
1/2
✓ Branch 0 taken 521167 times.
✗ Branch 1 not taken.
521167 DBUG_RETURN(0);
13115 }
13116
13117
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3822746 times.
3822746 if (wsrep_protocol_version == 0) {
13118 uint len;
13119 char keyval[WSREP_MAX_SUPPORTED_KEY_LENGTH + 1] = {'\0'};
13120 char *key = &keyval[0];
13121 bool is_null;
13122
13123 len = wsrep_store_key_val_for_row(thd, table, 0, key,
13124 WSREP_MAX_SUPPORTED_KEY_LENGTH, record0,
13125 &is_null, m_prebuilt);
13126
13127 if (!is_null) {
13128 rcode = wsrep_append_key(thd, trx, table_share, keyval, len, key_type);
13129 if (rcode) DBUG_RETURN(rcode);
13130 } else {
13131 WSREP_DEBUG("Skip appending NULL key (proto 0): %s",
13132 wsrep_thd_query(thd));
13133 }
13134 } else {
13135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3822746 times.
3822746 ut_a(table->s->keys <= 256);
13136 uint i;
13137 3822746 bool hasPK = false;
13138
13139
2/2
✓ Branch 0 taken 2189466 times.
✓ Branch 1 taken 1635422 times.
3824888 for (i = 0; i < table->s->keys; ++i) {
13140 2189466 KEY *key_info = table->key_info + i;
13141
2/2
✓ Branch 0 taken 2187324 times.
✓ Branch 1 taken 2142 times.
2189466 if (key_info->flags & HA_NOSAME) {
13142 2187324 hasPK = true;
13143 2187324 break;
13144 }
13145 }
13146
13147
2/2
✓ Branch 0 taken 2205001 times.
✓ Branch 1 taken 3822745 times.
6027746 for (i = 0; i < table->s->keys; ++i) {
13148 2205001 KEY *key_info = table->key_info + i;
13149
13150
1/2
✓ Branch 0 taken 2205001 times.
✗ Branch 1 not taken.
2205001 dict_index_t *idx = innobase_get_index(i);
13151
1/2
✓ Branch 0 taken 2205001 times.
✗ Branch 1 not taken.
2205001 dict_table_t *tab = (idx) ? idx->table : NULL;
13152
13153 /* keyval[] shall contain an ordinal number at byte 0
13154 and the actual key data shall be written at byte 1.
13155 Hence the total data length is the key length + 1 */
13156 2205001 char keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH + 1] = {'\0'};
13157 2205001 char keyval1[WSREP_MAX_SUPPORTED_KEY_LENGTH + 1] = {'\0'};
13158 2205001 keyval0[0] = (char)i;
13159 2205001 keyval1[0] = (char)i;
13160 2205001 char *key0 = &keyval0[1];
13161 2205001 char *key1 = &keyval1[1];
13162
13163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2205001 times.
2205001 if (!tab) {
13164 WSREP_WARN("MySQL-InnoDB key mismatch %s %s", table->s->table_name.str,
13165 key_info->name);
13166 }
13167
13168 const bool referenced_by_fk =
13169
1/2
✓ Branch 0 taken 2205001 times.
✗ Branch 1 not taken.
2205001 dict_table_is_referenced_by_foreign_key(m_prebuilt->table);
13170
13171 /* !hasPK == table with no PK,
13172 must append all non-unique keys */
13173
8/10
✓ Branch 0 taken 2142 times.
✓ Branch 1 taken 2202859 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2142 times.
✓ Branch 4 taken 15122 times.
✓ Branch 5 taken 2187737 times.
✓ Branch 6 taken 15122 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2189886 times.
✓ Branch 9 taken 15115 times.
2220123 if ((!hasPK && wsrep_certify_nonPK) || key_info->flags & HA_NOSAME ||
13174
4/6
✓ Branch 0 taken 15122 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15115 times.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 15115 times.
15122 ((tab && wsrep_is_FK_index(tab, idx)) ||
13175 (!tab && referenced_by_fk))) {
13176 bool is_null0;
13177
1/2
✓ Branch 0 taken 2189886 times.
✗ Branch 1 not taken.
2189886 uint len0 = wsrep_store_key_val_for_row(thd, table, i, key0,
13178 WSREP_MAX_SUPPORTED_KEY_LENGTH,
13179 record0, &is_null0, m_prebuilt);
13180
2/2
✓ Branch 0 taken 606490 times.
✓ Branch 1 taken 1583396 times.
2189886 if (record1) {
13181 bool is_null1;
13182
1/2
✓ Branch 0 taken 606490 times.
✗ Branch 1 not taken.
606490 uint len1 = wsrep_store_key_val_for_row(
13183 thd, table, i, key1, WSREP_MAX_SUPPORTED_KEY_LENGTH, record1,
13184 &is_null1, m_prebuilt);
13185
13186
3/4
✓ Branch 0 taken 606490 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 606488 times.
✓ Branch 3 taken 2 times.
606490 if (is_null0 != is_null1 || len0 != len1 ||
13187
2/2
✓ Branch 0 taken 2241 times.
✓ Branch 1 taken 604247 times.
606488 memcmp(key0, key1, len0)) {
13188 /* This key has chaged. If it
13189 is unique, this is an exclusive
13190 operation -> upgrade key type */
13191
2/2
✓ Branch 0 taken 1240 times.
✓ Branch 1 taken 1003 times.
2243 if (key_info->flags & HA_NOSAME) {
13192 1240 key_type = WSREP_SERVICE_KEY_EXCLUSIVE;
13193 }
13194
13195
1/2
✓ Branch 0 taken 2243 times.
✗ Branch 1 not taken.
2243 if (!is_null1) {
13196 4486 rcode = wsrep_append_key(thd, trx, table_share, keyval1,
13197 /* for len1+1 see keyval1
13198 initialization comment */
13199
1/2
✓ Branch 0 taken 2243 times.
✗ Branch 1 not taken.
2243 len1 + 1, key_type);
13200
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2243 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2243 if (rcode) DBUG_RETURN(rcode);
13201 }
13202 }
13203 }
13204
13205
2/2
✓ Branch 0 taken 2189883 times.
✓ Branch 1 taken 3 times.
2189886 if (!is_null0) {
13206 4379766 rcode = wsrep_append_key(thd, trx, table_share,
13207 /* for len0+1 see keyval0
13208 initialization comment */
13209
1/2
✓ Branch 0 taken 2189883 times.
✗ Branch 1 not taken.
2189883 keyval0, len0 + 1, key_type);
13210
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2189882 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2189883 if (rcode) DBUG_RETURN(rcode);
13211
13212
3/4
✓ Branch 0 taken 2149 times.
✓ Branch 1 taken 2187733 times.
✓ Branch 2 taken 2149 times.
✗ Branch 3 not taken.
2189882 if (key_info->flags & HA_NOSAME ||
13213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2149 times.
2149 key_type == WSREP_SERVICE_KEY_SHARED ||
13214 key_type == WSREP_SERVICE_KEY_REFERENCE)
13215 2187733 key_appended = true;
13216 } else {
13217
1/26
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
3 WSREP_DEBUG("NULL key skipped: %s", wsrep_thd_query(thd));
13218 }
13219 }
13220 }
13221 }
13222
13223 /* if no PK, calculate hash of full row, to be the key value */
13224
4/4
✓ Branch 0 taken 1635425 times.
✓ Branch 1 taken 2187320 times.
✓ Branch 2 taken 1635424 times.
✓ Branch 3 taken 1 times.
3822745 if (!key_appended && wsrep_certify_nonPK) {
13225 uchar digest[16];
13226 int rcode;
13227
13228
1/2
✓ Branch 0 taken 1635424 times.
✗ Branch 1 not taken.
1635424 wsrep_calc_row_hash(digest, record0, table, m_prebuilt, thd);
13229
2/4
✓ Branch 0 taken 1635424 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1635424 times.
1635424 if ((rcode = wsrep_append_key(thd, trx, table_share, (const char *)digest,
13230 16, key_type))) {
13231 DBUG_RETURN(rcode);
13232 }
13233
13234
2/2
✓ Branch 0 taken 4854 times.
✓ Branch 1 taken 1630570 times.
1635424 if (record1) {
13235
1/2
✓ Branch 0 taken 4854 times.
✗ Branch 1 not taken.
4854 wsrep_calc_row_hash(digest, record1, table, m_prebuilt, thd);
13236
2/4
✓ Branch 0 taken 4854 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4854 times.
4854 if ((rcode = wsrep_append_key(thd, trx, table_share, (const char *)digest,
13237 16, key_type))) {
13238 DBUG_RETURN(rcode);
13239 }
13240 }
13241
1/2
✓ Branch 0 taken 1635424 times.
✗ Branch 1 not taken.
1635424 DBUG_RETURN(0);
13242 }
13243
13244 /* If certification of table with non-PK is blocked by setting
13245 relevant configuration option wsrep_certify_nonPK = OFF/0 then
13246 ensure that thd->wsrep_ws_handle->trx_id = WSREP_UNDEFINED_TRX_ID.
13247 If not then make sure you set it to WSREP_UNDEFINED_TRX_ID.
13248 But what may cause trx_id to set if append-key is blocked ?
13249 CREATE TABLE ... SELECT statement will cause a fake_trx_id to set
13250 while processing SELECT statement. */
13251
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2187320 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2187321 if (!key_appended && !wsrep_certify_nonPK) {
13252
10/22
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
1 WSREP_WARN(
13253 "Table without explict primary key (not-recommended)"
13254 " and certification of nonPK table is OFF too");
13255 // wsrep_ws_handle_for_trx(&thd->wsrep_ws_handle, WSREP_UNDEFINED_TRX_ID);
13256 }
13257
13258
1/2
✓ Branch 0 taken 2187321 times.
✗ Branch 1 not taken.
2187321 DBUG_RETURN(0);
13259 }
13260 #endif /* WITH_WSREP */
13261
13262 /**
13263 Store a reference to the current row to 'ref' field of the handle.
13264 Note that in the case where we have generated the clustered index for the
13265 table, the function parameter is illogical: we MUST ASSUME that 'record'
13266 is the current 'position' of the handle, because if row ref is actually
13267 the row id internally generated in InnoDB, then 'record' does not contain
13268 it. We just guess that the row id must be for the record where the handle
13269 was positioned the last time.
13270 @param[in] record row in MySQL format */
13271 9085150 void ha_innobase::position(const uchar *record) {
13272 uint len;
13273
13274
1/2
✓ Branch 0 taken 9085151 times.
✗ Branch 1 not taken.
9085150 DBUG_TRACE;
13275
3/6
✓ Branch 0 taken 9085151 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9085151 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 9085151 times.
9085151 assert(m_prebuilt->trx == thd_to_trx(ha_thd()));
13276
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9085151 times.
9085151 assert(table_share->is_missing_primary_key() ==
13277 (bool)m_prebuilt->clust_index_was_generated);
13278
13279
2/2
✓ Branch 0 taken 8327159 times.
✓ Branch 1 taken 757992 times.
9085151 if (m_prebuilt->clust_index_was_generated) {
13280 /* No primary key was defined for the table and we
13281 generated the clustered index from row id: the
13282 row reference will be the row id, not any key value
13283 that MySQL knows of */
13284
13285 8327159 len = DATA_ROW_ID_LEN;
13286
13287 8327159 memcpy(ref, m_prebuilt->row_id, len);
13288 } else {
13289 /* Copy primary key as the row reference */
13290 757992 KEY *key_info = table->key_info + table_share->primary_key;
13291
1/2
✓ Branch 0 taken 757992 times.
✗ Branch 1 not taken.
757992 key_copy(ref, (uchar *)record, key_info, key_info->key_length);
13292 757992 len = key_info->key_length;
13293 }
13294
13295 /* We assume that the 'ref' value len is always fixed for the same
13296 table. */
13297
13298
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9085151 times.
9085151 if (len != ref_length) {
13299 log_errlog(ERROR_LEVEL, ER_INNODB_DIFF_IN_REF_LEN, (ulong)len,
13300 (ulong)ref_length);
13301 }
13302 9085151 }
13303
13304 /** Set up base columns for virtual column
13305 @param[in] table the InnoDB table
13306 @param[in] field MySQL field
13307 @param[in,out] v_col virtual column to be set up */
13308 28050 void innodb_base_col_setup(dict_table_t *table, const Field *field,
13309 dict_v_col_t *v_col) {
13310 28050 int n = 0;
13311
13312
2/2
✓ Branch 0 taken 499606 times.
✓ Branch 1 taken 28050 times.
527656 for (uint i = 0; i < field->table->s->fields; ++i) {
13313 499606 const Field *base_field = field->table->field[i];
13314
13315
6/6
✓ Branch 0 taken 123461 times.
✓ Branch 1 taken 376145 times.
✓ Branch 2 taken 27513 times.
✓ Branch 3 taken 95948 times.
✓ Branch 4 taken 27513 times.
✓ Branch 5 taken 472093 times.
623067 if (!base_field->is_virtual_gcol() &&
13316 123461 bitmap_is_set(&field->gcol_info->base_columns_map, i)) {
13317 ulint z;
13318
13319
1/2
✓ Branch 0 taken 52467 times.
✗ Branch 1 not taken.
52467 for (z = 0; z < table->n_cols; z++) {
13320 52467 const char *name = table->get_col_name(z);
13321
2/2
✓ Branch 0 taken 27513 times.
✓ Branch 1 taken 24954 times.
52467 if (!innobase_strcasecmp(name, base_field->field_name)) {
13322 27513 break;
13323 }
13324 }
13325
13326
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27513 times.
27513 ut_ad(z != table->n_cols);
13327
13328 27513 v_col->base_col[n] = table->get_col(z);
13329
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27513 times.
27513 ut_ad(v_col->base_col[n]->ind == z);
13330 27513 n++;
13331 }
13332 }
13333 28050 }
13334
13335 /** Set up base columns for stored column
13336 @param[in] table InnoDB table
13337 @param[in] field MySQL field
13338 @param[in,out] s_col stored column */
13339 1589 void innodb_base_col_setup_for_stored(const dict_table_t *table,
13340 const Field *field, dict_s_col_t *s_col) {
13341 1589 ulint n = 0;
13342
13343
2/2
✓ Branch 0 taken 2472 times.
✓ Branch 1 taken 41 times.
2513 for (uint i = 0; i < field->table->s->fields; ++i) {
13344 2472 const Field *base_field = field->table->field[i];
13345
13346
8/8
✓ Branch 0 taken 240 times.
✓ Branch 1 taken 2232 times.
✓ Branch 2 taken 127 times.
✓ Branch 3 taken 113 times.
✓ Branch 4 taken 1592 times.
✓ Branch 5 taken 767 times.
✓ Branch 6 taken 1592 times.
✓ Branch 7 taken 880 times.
4831 if (!innobase_is_v_fld(base_field) &&
13347 2359 bitmap_is_set(&field->gcol_info->base_columns_map, i)) {
13348 ulint z;
13349
1/2
✓ Branch 0 taken 2385 times.
✗ Branch 1 not taken.
2385 for (z = 0; z < table->n_cols; z++) {
13350 2385 const char *name = table->get_col_name(z);
13351
2/2
✓ Branch 0 taken 1592 times.
✓ Branch 1 taken 793 times.
2385 if (!innobase_strcasecmp(name, base_field->field_name)) {
13352 1592 break;
13353 }
13354 }
13355
13356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1592 times.
1592 ut_ad(z != table->n_cols);
13357
13358 1592 s_col->base_col[n] = table->get_col(z);
13359 1592 n++;
13360
13361
2/2
✓ Branch 0 taken 1548 times.
✓ Branch 1 taken 44 times.
1592 if (n == s_col->num_base) {
13362 1548 break;
13363 }
13364 }
13365 }
13366 1589 }
13367
13368 /** If encryption is requested, check for master key availability
13369 and set the encryption flag in table flags
13370 @param[in,out] table table object
13371 @return on success DB_SUCCESS else DB_UNSPPORTED on failure */
13372 1931 dberr_t create_table_info_t::enable_master_key_encryption(dict_table_t *table) {
13373 1931 const char *encrypt = m_create_info->encrypt_type.str;
13374
13375
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1931 times.
1931 if (Encryption::is_none(encrypt)) return (DB_SUCCESS);
13376
13377 /* If table is part of tablespace - no need for retrieving
13378 master key as tablespace key was already decrypted
13379 either by validate_first_page or during tablespace creation.
13380 Just set the encryption flag and return. */
13381
2/2
✓ Branch 0 taken 859 times.
✓ Branch 1 taken 1072 times.
1931 if (!(m_flags2 & DICT_TF2_USE_FILE_PER_TABLE)) {
13382 859 DICT_TF2_FLAG_SET(table, DICT_TF2_ENCRYPTION_FILE_PER_TABLE);
13383 859 return (DB_SUCCESS);
13384 }
13385
13386 /* Set the encryption flag. */
13387 1072 byte *master_key = nullptr;
13388 uint32_t master_key_id;
13389
13390 /* Check if keyring is ready. */
13391 1072 Encryption::get_master_key(&master_key_id, &master_key);
13392
13393 1072 dberr_t err = DB_SUCCESS;
13394
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 1049 times.
1072 if (master_key == nullptr) {
13395
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0));
13396 23 err = DB_UNSUPPORTED;
13397 } else {
13398
1/2
✓ Branch 0 taken 1049 times.
✗ Branch 1 not taken.
1049 my_free(master_key);
13399 1049 DICT_TF2_FLAG_SET(table, DICT_TF2_ENCRYPTION_FILE_PER_TABLE);
13400 }
13401
13402 1072 return (err);
13403 }
13404
13405 /** Retrive keyring encryption mode
13406 @param[in] encrypt_type from ENCRYPTION clause
13407 @param[in] explicit_encryption was ENCRYPTION clause used
13408 @param[in] flags tabelspace flags
13409 @retval FIL_ENCRYPTION_OFF tablespace should be skipped by
13410 encryption threads
13411 FIL_ENCRYPTION_DEFAULT online encryption allowed by
13412 encryption threads
13413 FIL_ENCRYPTION_ON table should be keyring encrypted */
13414 335405 static fil_encryption_t get_encryption_mode(const char *encrypt_type,
13415 bool explicit_encryption) {
13416
6/6
✓ Branch 0 taken 509 times.
✓ Branch 1 taken 334896 times.
✓ Branch 2 taken 241 times.
✓ Branch 3 taken 268 times.
✓ Branch 4 taken 241 times.
✓ Branch 5 taken 335164 times.
335405 if (explicit_encryption && innobase_strcasecmp(encrypt_type, "n") == 0) {
13417 241 return FIL_ENCRYPTION_OFF;
13418 }
13419
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 335165 times.
335164 if (Encryption::is_keyring(encrypt_type)) {
13420 return FIL_ENCRYPTION_ON;
13421 }
13422 335165 return FIL_ENCRYPTION_DEFAULT;
13423 }
13424
13425 5 dberr_t create_table_info_t::check_tablespace_key(
13426 const EncryptionKeyId encryption_key_id) {
13427
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!Encryption::tablespace_key_exists_or_create_new_one_if_does_not_exist(
13428 encryption_key_id, server_uuid)) {
13429 my_printf_error(
13430 ER_ILLEGAL_HA_CREATE_OPTION,
13431 "Seems that keyring is down. It is not possible to create encrypted "
13432 "tables "
13433 " without keyring. Please install a keyring and try again.",
13434 MYF(0));
13435 return (DB_UNSUPPORTED);
13436 }
13437 5 return DB_SUCCESS;
13438 }
13439
13440 /** Enable keyring encryption for table
13441 @param[in,out] table table to have its encryption flag set
13442 in case it should be KEYRING encrypted
13443 @param[out] keyring_encryption_mode FIL_ENCRYPTION_ON |
13444 FIL_ENCRYPTION_OFF | FIL_ENCRYPTION_DEFAULT
13445 @retval DB_UNSUPPORTED on error
13446 DB_SUCCESS on success */
13447 334520 dberr_t create_table_info_t::enable_keyring_encryption(
13448 dict_table_t *table, fil_encryption_t &keyring_encryption_mode) {
13449 334521 keyring_encryption_mode =
13450 669041 get_encryption_mode(m_create_info->encrypt_type.str,
13451 334520 m_create_info->used_fields & HA_CREATE_USED_ENCRYPT);
13452
13453
1/2
✓ Branch 0 taken 334522 times.
✗ Branch 1 not taken.
669043 bool is_encrypted = keyring_encryption_mode == FIL_ENCRYPTION_ON ||
13454
3/4
✓ Branch 0 taken 334522 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 334516 times.
669044 (keyring_encryption_mode == FIL_ENCRYPTION_DEFAULT &&
13455 334522 Encryption::is_online_encryption_on());
13456
13457
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 334516 times.
334521 if (is_encrypted)
13458 5 DICT_TF2_FLAG_SET(table, DICT_TF2_ENCRYPTION_FILE_PER_TABLE);
13459
13460
3/4
✓ Branch 0 taken 334515 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 334515 times.
334521 if (is_encrypted || m_create_info->was_encryption_key_id_set)
13461 6 return check_tablespace_key(m_create_info->encryption_key_id);
13462
13463 334515 return DB_SUCCESS;
13464 }
13465
13466 /** Create a table definition to an InnoDB database.
13467 @param[in] dd_table dd::Table or nullptr for intrinsic table
13468 @param[in] old_part_table dd::Table from an old partition for partitioned
13469 table, NULL otherwise.
13470 @return HA_* level error */
13471 348223 [[nodiscard]] inline int create_table_info_t::create_table_def(
13472 const dd::Table *dd_table, const dd::Table *old_part_table) {
13473 dict_table_t *table;
13474 ulint n_cols;
13475 348223 dberr_t err = DB_SUCCESS;
13476 ulint col_type;
13477 ulint col_len;
13478 ulint compressed;
13479 ulint i;
13480 348223 ulint j = 0;
13481 348223 ulint doc_id_col = 0;
13482 348223 bool has_doc_id_col = false;
13483 mem_heap_t *heap;
13484 348223 ulint num_v = 0;
13485 348223 ulint num_m_v = 0;
13486 348223 space_id_t space_id = 0;
13487 348223 dd::Object_id dd_space_id = dd::INVALID_OBJECT_ID;
13488 ulint actual_n_cols;
13489
13490 fil_encryption_t keyring_encryption_option =
13491 348223 Encryption::none_explicitly_specified(m_create_info->explicit_encryption,
13492 348223 m_create_info->encrypt_type.str)
13493
2/2
✓ Branch 0 taken 11742 times.
✓ Branch 1 taken 336481 times.
348223 ? FIL_ENCRYPTION_OFF
13494 348223 : FIL_ENCRYPTION_DEFAULT;
13495
13496 348223 uint32_t i_c = 0;
13497 348223 uint32_t c_c = 0;
13498 348223 uint32_t t_c = 0;
13499 348223 uint32_t c_r_v = 0;
13500
13501
1/2
✓ Branch 0 taken 348225 times.
✗ Branch 1 not taken.
348223 DBUG_TRACE;
13502
5/8
✓ Branch 0 taken 348225 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 348224 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 348214 times.
✓ Branch 6 taken 10 times.
✗ Branch 7 not taken.
348225 DBUG_PRINT("enter", ("table_name: %s", m_table_name));
13503
13504
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348224 times.
348224 assert(m_trx->mysql_thd == m_thd);
13505
13506 bool part_table_with_instant_cols =
13507
5/6
✓ Branch 0 taken 133 times.
✓ Branch 1 taken 348091 times.
✓ Branch 2 taken 133 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 121 times.
✓ Branch 5 taken 12 times.
348224 (old_part_table != nullptr && dd_table_has_row_versions(*old_part_table));
13508
13509 /* MySQL does the name length check. But we do additional check
13510 on the name length here */
13511 348224 const size_t table_name_len = strlen(m_table_name);
13512
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348224 times.
348224 if (table_name_len > MAX_FULL_NAME_LEN) {
13513 push_warning_printf(m_thd, Sql_condition::SL_WARNING, ER_WRONG_TABLE_NAME,
13514 "InnoDB: Table Name or Database Name is too long");
13515
13516 return HA_ERR_WRONG_TABLE_NAME;
13517 }
13518
13519 /* Make sure that the table name is acceptable. */
13520
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348224 times.
348224 if (m_table_name[table_name_len - 1] == '/') {
13521 push_warning_printf(m_thd, Sql_condition::SL_WARNING, ER_WRONG_TABLE_NAME,
13522 "InnoDB: Table name is empty");
13523
13524 return HA_ERR_WRONG_TABLE_NAME;
13525 }
13526
13527 fts_aux_table_t aux_table;
13528
3/4
✓ Branch 0 taken 348222 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 348196 times.
348224 if (fts_is_aux_table_name(&aux_table, m_table_name, strlen(m_table_name))) {
13529
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 push_warning_printf(
13530 m_thd, Sql_condition::SL_WARNING, ER_WRONG_TABLE_NAME,
13531 "Invalid table name. `%s` has the form of an FTS auxiliary table name",
13532 m_table_name);
13533 26 return HA_ERR_WRONG_TABLE_NAME;
13534 }
13535
13536 348196 n_cols = m_form->s->fields;
13537
13538 /* Find out any virtual column */
13539
2/2
✓ Branch 0 taken 2485532 times.
✓ Branch 1 taken 348199 times.
2833731 for (i = 0; i < n_cols; i++) {
13540 2485532 Field *field = m_form->field[i];
13541
13542
7/10
✓ Branch 0 taken 7992 times.
✓ Branch 1 taken 2477540 times.
✓ Branch 2 taken 1577 times.
✓ Branch 3 taken 6415 times.
✓ Branch 4 taken 2479119 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2479119 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 2485535 times.
2485532 ut_ad(!(!innobase_is_v_fld(field) && innobase_is_multi_value_fld(field)));
13543
13544
4/4
✓ Branch 0 taken 7992 times.
✓ Branch 1 taken 2477543 times.
✓ Branch 2 taken 6415 times.
✓ Branch 3 taken 1577 times.
2485535 if (innobase_is_v_fld(field)) {
13545 6415 num_v++;
13546
13547
3/4
✓ Branch 0 taken 6415 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 243 times.
✓ Branch 3 taken 6172 times.
6415 if (innobase_is_multi_value_fld(field)) {
13548 243 num_m_v++;
13549 }
13550 }
13551 }
13552
13553 /* Check whether there already exists a FTS_DOC_ID column */
13554
3/4
✓ Branch 0 taken 348197 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
✓ Branch 3 taken 348159 times.
348199 if (create_table_check_doc_id_col(m_trx->mysql_thd, m_form, &doc_id_col)) {
13555 /* Raise error if the Doc ID column is of wrong type or name */
13556
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 37 times.
38 if (doc_id_col == ULINT_UNDEFINED) {
13557 1 err = DB_ERROR;
13558 1 goto error_ret;
13559 } else {
13560 37 has_doc_id_col = true;
13561 }
13562 }
13563
13564 /* For single-table tablespaces, we pass 0 as the space id, and then
13565 determine the actual space id when the tablespace is created. */
13566
2/2
✓ Branch 0 taken 24392 times.
✓ Branch 1 taken 323804 times.
348196 if (DICT_TF_HAS_SHARED_SPACE(m_flags)) {
13567
3/6
✓ Branch 0 taken 24392 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24392 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 24392 times.
24392 ut_ad(m_tablespace != nullptr && m_tablespace[0] != '\0');
13568
13569
1/2
✓ Branch 0 taken 24392 times.
✗ Branch 1 not taken.
24392 space_id = fil_space_get_id_by_name(m_tablespace);
13570
2/4
✓ Branch 0 taken 24392 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24392 times.
✗ Branch 3 not taken.
24392 dd_space_id = (dd_table != nullptr ? dd_table->tablespace_id()
13571 : dd::INVALID_OBJECT_ID);
13572 }
13573
13574 /* Adjust the number of columns for the FTS hidden field */
13575 348196 actual_n_cols = n_cols;
13576
4/4
✓ Branch 0 taken 470 times.
✓ Branch 1 taken 347726 times.
✓ Branch 2 taken 451 times.
✓ Branch 3 taken 19 times.
348196 if (m_flags2 & (DICT_TF2_FTS | DICT_TF2_FTS_ADD_DOC_ID) && !has_doc_id_col) {
13577 451 actual_n_cols += 1;
13578 }
13579
13580
2/2
✓ Branch 0 taken 121 times.
✓ Branch 1 taken 348075 times.
348196 if (part_table_with_instant_cols) {
13581
1/2
✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
121 dd_table_get_column_counters(*old_part_table, i_c, c_c, t_c, c_r_v);
13582 }
13583
13584
1/2
✓ Branch 0 taken 348198 times.
✗ Branch 1 not taken.
348196 table = dict_mem_table_create(m_table_name, space_id, actual_n_cols, num_v,
13585 num_m_v, m_flags, m_flags2, t_c - c_c);
13586
13587 /* Set dd tablespace id */
13588 348198 table->dd_space_id = dd_space_id;
13589
13590 /* Set the hidden doc_id column. */
13591
2/2
✓ Branch 0 taken 470 times.
✓ Branch 1 taken 347728 times.
348198 if (m_flags2 & (DICT_TF2_FTS | DICT_TF2_FTS_ADD_DOC_ID)) {
13592
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 451 times.
470 table->fts->doc_col = has_doc_id_col ? doc_id_col : n_cols - num_v;
13593 }
13594
13595
2/2
✓ Branch 0 taken 429 times.
✓ Branch 1 taken 347769 times.
348198 if (DICT_TF_HAS_DATA_DIR(m_flags)) {
13596
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 428 times.
429 ut_a(strlen(m_remote_path) != 0);
13597
13598
1/2
✓ Branch 0 taken 428 times.
✗ Branch 1 not taken.
428 table->data_dir_path = mem_heap_strdup(table->heap, m_remote_path);
13599
13600 } else {
13601 347769 table->data_dir_path = nullptr;
13602 }
13603
13604
2/2
✓ Branch 0 taken 24392 times.
✓ Branch 1 taken 323806 times.
348197 if (DICT_TF_HAS_SHARED_SPACE(m_flags)) {
13605
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24392 times.
24392 ut_ad(strlen(m_tablespace));
13606
1/2
✓ Branch 0 taken 24392 times.
✗ Branch 1 not taken.
24392 table->tablespace = mem_heap_strdup(table->heap, m_tablespace);
13607 } else {
13608 323806 table->tablespace = nullptr;
13609 }
13610
13611 /* Initialize row version and column counts for new table */
13612
2/2
✓ Branch 0 taken 348077 times.
✓ Branch 1 taken 121 times.
348198 if (!part_table_with_instant_cols) {
13613 348077 table->current_row_version = 0;
13614 348077 table->initial_col_count = n_cols - num_v;
13615 348077 table->current_col_count = table->initial_col_count;
13616 348077 table->total_col_count = table->initial_col_count;
13617 } else {
13618 /* This is a new partition getting created. We need to inherit INSTANT
13619 instant metadata from old partition table */
13620 121 table->initial_col_count = i_c;
13621 121 table->current_col_count = c_c;
13622 121 table->total_col_count = t_c;
13623 121 table->current_row_version = c_r_v;
13624 121 table->discard_after_ddl = true;
13625
13626 #ifdef UNIV_DEBUG
13627 /* Get and set current row version for table */
13628 121 uint32_t v = 0;
13629
6/10
✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 121 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 121 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 791 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 791 times.
✓ Branch 9 taken 121 times.
912 for (auto col : old_part_table->columns()) {
13630
3/4
✓ Branch 0 taken 791 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 70 times.
✓ Branch 3 taken 721 times.
791 if (dd_column_is_dropped(col)) {
13631
1/2
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
70 uint32_t value = dd_column_get_version_dropped(col);
13632 70 v = std::max(v, value);
13633 70 continue;
13634 70 }
13635
13636
3/4
✓ Branch 0 taken 721 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 169 times.
✓ Branch 3 taken 552 times.
721 if (dd_column_is_added(col)) {
13637
1/2
✓ Branch 0 taken 169 times.
✗ Branch 1 not taken.
169 uint32_t value = dd_column_get_version_added(col);
13638 169 v = std::max(v, value);
13639 169 continue;
13640 169 }
13641 }
13642
2/4
✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 121 times.
121 ut_ad(dd_is_valid_row_version(v));
13643
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 121 times.
121 ut_ad(table->current_row_version == v);
13644 #endif
13645 }
13646
13647
1/2
✓ Branch 0 taken 348198 times.
✗ Branch 1 not taken.
348198 heap = mem_heap_create(1000, UT_LOCATION_HERE);
13648
13649
2/2
✓ Branch 0 taken 2485526 times.
✓ Branch 1 taken 348195 times.
2833721 for (i = 0; i < n_cols; i++) {
13650 ulint nulls_allowed;
13651 ulint unsigned_type;
13652 ulint binary_type;
13653 ulint long_true_varchar;
13654 ulint charset_no;
13655 ulint is_virtual;
13656 ulint is_multi_val;
13657 2485526 bool is_stored = false;
13658
13659 2485526 Field *field = m_form->field[i];
13660
13661 /* Generate a unique column name by pre-pending table-name for
13662 intrinsic tables. For other tables (including normal
13663 temporary) column names are unique. If not, MySQL layer will
13664 block such statement.
13665 This is work-around fix till Optimizer can handle this issue
13666 (probably 5.7.4+). */
13667 char field_name[MAX_FULL_NAME_LEN + 2 + 10];
13668
13669
6/8
✓ Branch 0 taken 2485526 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1705572 times.
✓ Branch 3 taken 779954 times.
✓ Branch 4 taken 1705572 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1705572 times.
✓ Branch 7 taken 779954 times.
2485526 if (table->is_intrinsic() && field->table) {
13670 1705572 snprintf(field_name, sizeof(field_name), "%s_%s_" ULINTPF,
13671 1705572 field->table->alias, field->field_name, i);
13672
13673 } else {
13674 779954 snprintf(field_name, sizeof(field_name), "%s", field->field_name);
13675 }
13676
13677
1/2
✓ Branch 0 taken 2485528 times.
✗ Branch 1 not taken.
2485526 col_type = get_innobase_type_from_mysql_type(&unsigned_type, field);
13678
13679
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2485528 times.
2485528 if (!col_type) {
13680 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
13681 ER_CANT_CREATE_TABLE,
13682 "Error creating table '%s' with"
13683 " column '%s'. Please check its"
13684 " column type and try to re-create"
13685 " the table with an appropriate"
13686 " column type.",
13687 table->name.m_name, field->field_name);
13688 goto err_col;
13689 }
13690
13691
2/2
✓ Branch 0 taken 982852 times.
✓ Branch 1 taken 1502674 times.
2485528 nulls_allowed = field->is_nullable() ? 0 : DATA_NOT_NULL;
13692
3/4
✓ Branch 0 taken 2485526 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1316866 times.
✓ Branch 3 taken 1168660 times.
2485526 binary_type = field->binary() ? DATA_BINARY_TYPE : 0;
13693
13694 2485526 charset_no = 0;
13695
13696
3/4
✓ Branch 0 taken 2485528 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1235870 times.
✓ Branch 3 taken 1249658 times.
2485526 if (dtype_is_string_type(col_type)) {
13697
1/2
✓ Branch 0 taken 1235870 times.
✗ Branch 1 not taken.
1235870 charset_no = (ulint)field->charset()->number;
13698
13699
3/4
✓ Branch 0 taken 1235870 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1235869 times.
1235870 DBUG_EXECUTE_IF("simulate_max_char_col",
13700 charset_no = MAX_CHAR_COLL_NUM + 1;);
13701
13702
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1235869 times.
1235870 if (charset_no > MAX_CHAR_COLL_NUM) {
13703 /* in data0type.h we assume that the
13704 number fits in one byte in prtype */
13705
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
13706 ER_CANT_CREATE_TABLE,
13707 "In InnoDB, charset-collation codes"
13708 " must be below 256."
13709 " Unsupported code %lu.",
13710 (ulong)charset_no);
13711
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 mem_heap_free(heap);
13712
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 dict_mem_table_free(table);
13713
13714 1 return ER_CANT_CREATE_TABLE;
13715 }
13716 }
13717
13718
1/2
✓ Branch 0 taken 2485525 times.
✗ Branch 1 not taken.
2485527 col_len = field->pack_length();
13719
13720 /* The MySQL pack length contains 1 or 2 bytes length field
13721 for a true VARCHAR. Let us subtract that, so that the InnoDB
13722 column length in the InnoDB data dictionary is the real
13723 maximum byte length of the actual data. */
13724
13725 2485525 long_true_varchar = 0;
13726
13727
3/4
✓ Branch 0 taken 2485526 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 930253 times.
✓ Branch 3 taken 1555273 times.
2485525 if (field->type() == MYSQL_TYPE_VARCHAR) {
13728
1/2
✓ Branch 0 taken 930253 times.
✗ Branch 1 not taken.
930253 col_len -= field->get_length_bytes();
13729
13730
3/4
✓ Branch 0 taken 930253 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 249743 times.
✓ Branch 3 taken 680510 times.
930253 if (field->get_length_bytes() == 2) {
13731 249743 long_true_varchar = DATA_LONG_TRUE_VARCHAR;
13732 }
13733 }
13734
13735
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2485526 times.
2485526 if (col_type == DATA_POINT) {
13736 col_len = DATA_POINT_LEN;
13737 }
13738
13739
4/4
✓ Branch 0 taken 7992 times.
✓ Branch 1 taken 2477534 times.
✓ Branch 2 taken 6415 times.
✓ Branch 3 taken 1577 times.
2485526 is_virtual = (innobase_is_v_fld(field)) ? DATA_VIRTUAL : 0;
13740 2485526 is_stored = innobase_is_s_fld(field);
13741 /* Check if the the field has COMPRESSED attribute */
13742 2485525 compressed = (field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED)
13743
2/2
✓ Branch 0 taken 2444 times.
✓ Branch 1 taken 2483081 times.
2485525 ? DATA_COMPRESSED
13744 : 0;
13745
13746
3/4
✓ Branch 0 taken 2485525 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 243 times.
✓ Branch 3 taken 2485282 times.
2485525 is_multi_val = innobase_is_multi_value_fld(field) ? DATA_MULTI_VALUE : 0;
13747
13748 /* First check whether the column to be added has a
13749 system reserved name. */
13750
3/4
✓ Branch 0 taken 2485527 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2485525 times.
2485525 if (dict_col_name_is_reserved(field_name)) {
13751
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_WRONG_COLUMN_NAME, MYF(0), field_name);
13752 2 err_col:
13753
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 dict_mem_table_free(table);
13754
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 mem_heap_free(heap);
13755
13756 2 err = DB_ERROR;
13757 2 goto error_ret;
13758 }
13759
13760
2/2
✓ Branch 0 taken 2479108 times.
✓ Branch 1 taken 6417 times.
2485525 if (!is_virtual) {
13761 2479108 uint32_t v_added = UINT32_UNDEFINED;
13762 2479108 uint32_t v_dropped = UINT32_UNDEFINED;
13763 2479108 uint32_t phy_pos = UINT32_UNDEFINED;
13764
13765
2/2
✓ Branch 0 taken 459 times.
✓ Branch 1 taken 2478649 times.
2479108 if (part_table_with_instant_cols) {
13766 const dd::Column *old_part_col =
13767
1/2
✓ Branch 0 taken 459 times.
✗ Branch 1 not taken.
459 dd_find_column(old_part_table, field_name);
13768
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 459 times.
459 ut_ad(old_part_col != nullptr);
13769
13770 /* Get version added */
13771
1/2
✓ Branch 0 taken 459 times.
✗ Branch 1 not taken.
459 v_added = dd_column_get_version_added(old_part_col);
13772
13773 /* This columns must be present */
13774
2/4
✓ Branch 0 taken 459 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 459 times.
459 ut_ad(!dd_column_is_dropped(old_part_col));
13775
13776 /* Get physical pos */
13777 459 const char *s = dd_column_key_strings[DD_INSTANT_PHYSICAL_POS];
13778
4/8
✓ Branch 0 taken 459 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 459 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 459 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 459 times.
459 ut_ad(old_part_col->se_private_data().exists(s));
13779
3/6
✓ Branch 0 taken 459 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 459 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 459 times.
✗ Branch 5 not taken.
459 old_part_col->se_private_data().get(s, &phy_pos);
13780 }
13781
13782
1/2
✓ Branch 0 taken 2479109 times.
✗ Branch 1 not taken.
2479109 dict_mem_table_add_col(
13783 table, heap, field_name, col_type,
13784 4958218 dtype_form_prtype((ulint)field->type() | nulls_allowed |
13785
1/2
✓ Branch 0 taken 2479109 times.
✗ Branch 1 not taken.
2479110 unsigned_type | binary_type |
13786 long_true_varchar | compressed,
13787 charset_no),
13788
2/4
✓ Branch 0 taken 2479108 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2479110 times.
✗ Branch 3 not taken.
2479108 col_len, !field->is_hidden_by_system(), phy_pos, v_added, v_dropped);
13789
13790
3/4
✓ Branch 0 taken 2479108 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 169 times.
✓ Branch 3 taken 2478939 times.
2479109 if (dd_is_valid_row_version(v_added)) {
13791
1/2
✓ Branch 0 taken 169 times.
✗ Branch 1 not taken.
169 mem_heap_t *instant_heap = mem_heap_create(1000, UT_LOCATION_HERE);
13792 const dd::Column *old_part_col =
13793
1/2
✓ Branch 0 taken 169 times.
✗ Branch 1 not taken.
169 dd_find_column(old_part_table, field_name);
13794
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 169 times.
169 ut_ad(old_part_col != nullptr);
13795
1/2
✓ Branch 0 taken 169 times.
✗ Branch 1 not taken.
169 dict_col_t *col = table->get_col(table->n_def - 1);
13796
2/4
✓ Branch 0 taken 169 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 169 times.
✗ Branch 3 not taken.
169 dd_parse_default_value(old_part_col->se_private_data(), col, heap);
13797
1/2
✓ Branch 0 taken 169 times.
✗ Branch 1 not taken.
169 mem_heap_free(instant_heap);
13798 }
13799 } else {
13800
2/2
✓ Branch 0 taken 243 times.
✓ Branch 1 taken 6174 times.
6417 if (is_multi_val) {
13801
1/2
✓ Branch 0 taken 243 times.
✗ Branch 1 not taken.
243 col_len = field->key_length();
13802 }
13803
1/2
✓ Branch 0 taken 6415 times.
✗ Branch 1 not taken.
6415 dict_mem_table_add_v_col(
13804 table, heap, field_name, col_type,
13805
1/2
✓ Branch 0 taken 6415 times.
✗ Branch 1 not taken.
6415 dtype_form_prtype((ulint)field->type() | nulls_allowed |
13806 6415 unsigned_type | binary_type |
13807
1/2
✓ Branch 0 taken 6415 times.
✗ Branch 1 not taken.
6415 long_true_varchar | is_virtual | is_multi_val |
13808 compressed,
13809 charset_no),
13810 6415 col_len, i, field->gcol_info->non_virtual_base_columns(),
13811
1/2
✓ Branch 0 taken 6415 times.
✗ Branch 1 not taken.
6417 !field->is_hidden_by_system());
13812 }
13813
13814
2/2
✓ Branch 0 taken 1577 times.
✓ Branch 1 taken 2483946 times.
2485523 if (is_stored) {
13815
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1577 times.
1577 ut_ad(!is_virtual);
13816 /* Added stored column in m_s_cols list. */
13817
1/2
✓ Branch 0 taken 1577 times.
✗ Branch 1 not taken.
1577 dict_mem_table_add_s_col(table,
13818 1577 field->gcol_info->non_virtual_base_columns());
13819 }
13820 }
13821
13822
2/2
✓ Branch 0 taken 2849 times.
✓ Branch 1 taken 345346 times.
348195 if (num_v) {
13823
2/2
✓ Branch 0 taken 14511 times.
✓ Branch 1 taken 2849 times.
17360 for (i = 0; i < n_cols; i++) {
13824 dict_v_col_t *v_col;
13825
13826 14511 Field *field = m_form->field[i];
13827
13828
4/4
✓ Branch 0 taken 7704 times.
✓ Branch 1 taken 6807 times.
✓ Branch 2 taken 1289 times.
✓ Branch 3 taken 6415 times.
14511 if (!innobase_is_v_fld(field)) {
13829 8096 continue;
13830 }
13831
13832
1/2
✓ Branch 0 taken 6415 times.
✗ Branch 1 not taken.
6415 v_col = dict_table_get_nth_v_col(table, j);
13833
13834 6415 j++;
13835
13836
1/2
✓ Branch 0 taken 6415 times.
✗ Branch 1 not taken.
6415 innodb_base_col_setup(table, field, v_col);
13837 }
13838 }
13839
13840 /** Fill base columns for the stored column present in the list. */
13841
5/6
✓ Branch 0 taken 1475 times.
✓ Branch 1 taken 346720 times.
✓ Branch 2 taken 1475 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1475 times.
✓ Branch 5 taken 346720 times.
348195 if (table->s_cols && table->s_cols->size()) {
13842
2/2
✓ Branch 0 taken 8534 times.
✓ Branch 1 taken 1475 times.
10009 for (i = 0; i < n_cols; i++) {
13843 8534 Field *field = m_form->field[i];
13844
13845
2/2
✓ Branch 0 taken 6957 times.
✓ Branch 1 taken 1577 times.
8534 if (!innobase_is_s_fld(field)) {
13846 6957 continue;
13847 }
13848
13849 1577 dict_s_col_list::iterator it;
13850
1/2
✓ Branch 0 taken 1752 times.
✗ Branch 1 not taken.
1752 for (it = table->s_cols->begin(); it != table->s_cols->end(); ++it) {
13851 1752 dict_s_col_t s_col = *it;
13852
13853
2/2
✓ Branch 0 taken 1577 times.
✓ Branch 1 taken 175 times.
1752 if (s_col.s_pos == i) {
13854
1/2
✓ Branch 0 taken 1577 times.
✗ Branch 1 not taken.
1577 innodb_base_col_setup_for_stored(table, field, &s_col);
13855 1577 break;
13856 }
13857 }
13858 }
13859 }
13860
13861 /* Add the FTS doc_id hidden column. */
13862
4/4
✓ Branch 0 taken 470 times.
✓ Branch 1 taken 347725 times.
✓ Branch 2 taken 451 times.
✓ Branch 3 taken 19 times.
348195 if (m_flags2 & (DICT_TF2_FTS | DICT_TF2_FTS_ADD_DOC_ID) && !has_doc_id_col) {
13863
1/2
✓ Branch 0 taken 449 times.
✗ Branch 1 not taken.
451 fts_add_doc_id_column(table, heap);
13864 }
13865
13866
2/2
✓ Branch 0 taken 336451 times.
✓ Branch 1 taken 11742 times.
348193 if (keyring_encryption_option != FIL_ENCRYPTION_OFF) {
13867 336451 err =
13868 336451 (Encryption::is_master_key_encryption(m_create_info->encrypt_type.str))
13869
3/4
✓ Branch 0 taken 1931 times.
✓ Branch 1 taken 334521 times.
✓ Branch 2 taken 1931 times.
✗ Branch 3 not taken.
336452 ? enable_master_key_encryption(table)
13870
1/2
✓ Branch 0 taken 334520 times.
✗ Branch 1 not taken.
334521 : enable_keyring_encryption(table, keyring_encryption_option);
13871 }
13872
13873
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 348170 times.
348193 if (err != DB_SUCCESS) {
13874
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 dict_mem_table_free(table);
13875
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 mem_heap_free(heap);
13876 23 goto error_ret;
13877 }
13878
13879
3/4
✓ Branch 0 taken 348170 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 153522 times.
✓ Branch 3 taken 194648 times.
348170 if (table->is_temporary()) {
13880
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 153521 times.
153522 if (m_create_info->compress.length > 0) {
13881
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 push_warning_printf(m_thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED,
13882 "InnoDB: Compression not supported for "
13883 "temporary tables");
13884
13885 1 err = DB_UNSUPPORTED;
13886
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 dict_mem_table_free(table);
13887 } else {
13888 /* Get a new table ID */
13889
1/2
✓ Branch 0 taken 153523 times.
✗ Branch 1 not taken.
153521 dict_table_assign_new_id(table);
13890
13891 /* Create temp tablespace if configured. */
13892 153523 KeyringEncryptionKeyIdInfo keyring_encryption_key_id;
13893 153523 keyring_encryption_key_id.was_encryption_key_id_set = false;
13894
1/2
✓ Branch 0 taken 153522 times.
✗ Branch 1 not taken.
153523 err = dict_build_tablespace_for_table(table, m_create_info, m_trx,
13895 FIL_ENCRYPTION_DEFAULT,
13896 keyring_encryption_key_id);
13897
13898
2/2
✓ Branch 0 taken 153519 times.
✓ Branch 1 taken 3 times.
153522 if (err == DB_SUCCESS) {
13899 /* Temp-table are maintained in memory and so
13900 can_be_evicted is false. */
13901 mem_heap_t *temp_table_heap;
13902
13903
1/2
✓ Branch 0 taken 153519 times.
✗ Branch 1 not taken.
153519 temp_table_heap = mem_heap_create(256, UT_LOCATION_HERE);
13904
13905 /* For intrinsic table (given that they are
13906 not shared beyond session scope), add
13907 it to session specific THD structure
13908 instead of adding it to dictionary cache. */
13909
3/4
✓ Branch 0 taken 153519 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 110975 times.
✓ Branch 3 taken 42544 times.
153519 if (table->is_intrinsic()) {
13910
1/2
✓ Branch 0 taken 110975 times.
✗ Branch 1 not taken.
110975 add_table_to_thread_cache(table, temp_table_heap, m_thd);
13911
13912 } else {
13913
1/2
✓ Branch 0 taken 42544 times.
✗ Branch 1 not taken.
42544 dict_table_add_system_columns(table, temp_table_heap);
13914
13915
1/2
✓ Branch 0 taken 42544 times.
✗ Branch 1 not taken.
42544 dict_sys_mutex_enter();
13916
1/2
✓ Branch 0 taken 42544 times.
✗ Branch 1 not taken.
42544 dict_table_add_to_cache(table, false);
13917
1/2
✓ Branch 0 taken 42544 times.
✗ Branch 1 not taken.
42544 dict_sys_mutex_exit();
13918 }
13919
13920
4/6
✓ Branch 0 taken 153519 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 153518 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
153519 DBUG_EXECUTE_IF("ib_ddl_crash_during_create2", DBUG_SUICIDE(););
13921
13922
1/2
✓ Branch 0 taken 153518 times.
✗ Branch 1 not taken.
153518 mem_heap_free(temp_table_heap);
13923 } else {
13924
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 dict_mem_table_free(table);
13925 }
13926 }
13927
13928 } else {
13929 194648 const char *algorithm = m_create_info->compress.str;
13930
13931 194648 err = DB_SUCCESS;
13932
13933 418183 if (!(m_flags2 & DICT_TF2_USE_FILE_PER_TABLE) &&
13934
6/6
✓ Branch 0 taken 28887 times.
✓ Branch 1 taken 165761 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 28885 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 194646 times.
194650 m_create_info->compress.length > 0 &&
13935
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 !Compression::is_none(algorithm)) {
13936
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 push_warning_printf(m_thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED,
13937 "InnoDB: Compression not supported for "
13938 "shared tablespaces");
13939
13940 2 algorithm = nullptr;
13941
13942 2 err = DB_UNSUPPORTED;
13943
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 dict_mem_table_free(table);
13944
13945
1/2
✓ Branch 0 taken 194646 times.
✗ Branch 1 not taken.
194646 } else if (Compression::validate(algorithm) != DB_SUCCESS ||
13946
6/6
✓ Branch 0 taken 194645 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 193907 times.
✓ Branch 3 taken 738 times.
✓ Branch 4 taken 818 times.
✓ Branch 5 taken 193828 times.
388553 m_form->s->row_type == ROW_TYPE_COMPRESSED ||
13947
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 193828 times.
193907 m_create_info->key_block_size > 0) {
13948 818 algorithm = nullptr;
13949 }
13950
13951 KeyringEncryptionKeyIdInfo keyring_encryption_key_id(
13952 194648 m_create_info->was_encryption_key_id_set,
13953 194648 m_create_info->encryption_key_id);
13954
13955
2/2
✓ Branch 0 taken 194646 times.
✓ Branch 1 taken 2 times.
194648 if (err == DB_SUCCESS) {
13956
1/2
✓ Branch 0 taken 194609 times.
✗ Branch 1 not taken.
194646 err = row_create_table_for_mysql(table, algorithm, m_create_info, m_trx,
13957 heap,
13958 keyring_encryption_option,
13959 keyring_encryption_key_id);
13960
13961
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 194609 times.
194609 if (err == DB_IO_NO_PUNCH_HOLE_FS) {
13962 ut_ad(!dict_table_in_shared_tablespace(table));
13963 my_error(ER_INNODB_COMPRESSION_FAILURE, MYF(0),
13964 "Punch hole not supported by the filesystem or the tablespace "
13965 "page size is not large enough.");
13966 }
13967
13968
4/4
✓ Branch 0 taken 194595 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 121 times.
✓ Branch 3 taken 194474 times.
194609 if (err == DB_SUCCESS && part_table_with_instant_cols) {
13969 /* Set phy_pos for system cols */
13970
13971 363 auto fn = [&](uint32_t sys_col, const char *name) {
13972 363 uint32_t phy_pos = UINT32_UNDEFINED;
13973
1/2
✓ Branch 0 taken 363 times.
✗ Branch 1 not taken.
363 dict_col_t *col = table->get_sys_col(sys_col);
13974
1/2
✓ Branch 0 taken 363 times.
✗ Branch 1 not taken.
363 const dd::Column *old_part_col = dd_find_column(old_part_table, name);
13975
2/2
✓ Branch 0 taken 101 times.
✓ Branch 1 taken 262 times.
363 if (old_part_col == nullptr) {
13976 /* If PK exists, DB_ROW_ID won't be part of table definition. */
13977
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 101 times.
101 ut_ad(strcmp(name, "DB_ROW_ID") == 0);
13978 101 return;
13979 }
13980
13981 262 const char *s = dd_column_key_strings[DD_INSTANT_PHYSICAL_POS];
13982
4/8
✓ Branch 0 taken 262 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 262 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 262 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 262 times.
262 ut_ad(old_part_col->se_private_data().exists(s));
13983
3/6
✓ Branch 0 taken 262 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 262 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 262 times.
✗ Branch 5 not taken.
262 old_part_col->se_private_data().get(s, &phy_pos);
13984 262 col->set_phy_pos(phy_pos);
13985 121 };
13986
13987
1/2
✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
121 fn(DATA_ROW_ID, "DB_ROW_ID");
13988
1/2
✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
121 fn(DATA_TRX_ID, "DB_TRX_ID");
13989
1/2
✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
121 fn(DATA_ROLL_PTR, "DB_ROLL_PTR");
13990
13991 /* Add INSTANT DROP columns metadata */
13992 121 IF_DEBUG(uint32_t row_version = 0;)
13993
1/2
✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
121 fill_dict_dropped_columns(old_part_table, table,
13994 IF_DEBUG(row_version, ) heap);
13995
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 121 times.
121 ut_ad(row_version <= table->current_row_version);
13996 }
13997 }
13998
13999
4/6
✓ Branch 0 taken 194611 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 194609 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
194611 DBUG_EXECUTE_IF("ib_crash_during_create_for_encryption", DBUG_SUICIDE(););
14000 }
14001
14002
1/2
✓ Branch 0 taken 348131 times.
✗ Branch 1 not taken.
348131 mem_heap_free(heap);
14003
14004
2/4
✓ Branch 0 taken 348131 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 348131 times.
348131 DBUG_EXECUTE_IF("ib_create_err_tablespace_exist",
14005 err = DB_TABLESPACE_EXISTS;);
14006
14007
2/4
✓ Branch 0 taken 348131 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 348131 times.
348131 if (err == DB_DUPLICATE_KEY || err == DB_TABLESPACE_EXISTS) {
14008 char display_name[FN_REFLEN];
14009 char *buf_end =
14010 innobase_convert_identifier(display_name, sizeof(display_name) - 1,
14011 m_table_name, strlen(m_table_name), m_thd);
14012
14013 *buf_end = '\0';
14014
14015 my_error(
14016 err == DB_DUPLICATE_KEY ? ER_TABLE_EXISTS_ERROR : ER_TABLESPACE_EXISTS,
14017 MYF(0), display_name);
14018
14019 if (err == DB_DUPLICATE_KEY) {
14020 /* 'this' may not be ready for get_dup_key(), see same
14021 error tweaking in rename_table(). */
14022 err = DB_ERROR;
14023 }
14024 }
14025
14026
4/4
✓ Branch 0 taken 348111 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 465 times.
✓ Branch 3 taken 347646 times.
348131 if (err == DB_SUCCESS && (m_flags2 & DICT_TF2_FTS)) {
14027
1/2
✓ Branch 0 taken 465 times.
✗ Branch 1 not taken.
465 dict_sys_mutex_enter();
14028
1/2
✓ Branch 0 taken 465 times.
✗ Branch 1 not taken.
465 fts_optimize_add_table(table);
14029
1/2
✓ Branch 0 taken 465 times.
✗ Branch 1 not taken.
465 dict_sys_mutex_exit();
14030 }
14031
14032
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 348111 times.
348131 if (err == DB_SUCCESS) {
14033 348111 m_table = table;
14034 }
14035
14036 20 error_ret:
14037
1/2
✓ Branch 0 taken 348157 times.
✗ Branch 1 not taken.
348157 return convert_error_code_to_mysql(err, m_flags, m_thd);
14038 348184 }
14039
14040 template <typename Index>
14041 const dd::Index *get_my_dd_index(const Index *index);
14042
14043 template <>
14044 379 const dd::Index *get_my_dd_index<dd::Index>(const dd::Index *dd_index) {
14045 379 return dd_index;
14046 }
14047
14048 template <>
14049 const dd::Index *get_my_dd_index<dd::Partition_index>(
14050 const dd::Partition_index *dd_index) {
14051 return (dd_index != nullptr) ? &dd_index->index() : nullptr;
14052 }
14053
14054 /** Creates an index in an InnoDB database. */
14055 179566 inline int create_index(
14056 trx_t *trx, /*!< in: InnoDB transaction handle */
14057 const TABLE *form, /*!< in: information on table
14058 columns and indexes */
14059 uint32_t flags, /*!< in: InnoDB table flags */
14060 const char *table_name, /*!< in: table name */
14061 uint key_num, /*!< in: index number */
14062 const dd::Table *dd_table) /*!< in: dd::Table for the table*/
14063 {
14064 dict_index_t *index;
14065 int error;
14066 const KEY *key;
14067 ulint ind_type;
14068 ulint *field_lengths;
14069 179566 uint32_t srid = 0;
14070 179566 bool has_srid = false;
14071 179566 bool multi_val_idx = false;
14072
14073
1/2
✓ Branch 0 taken 179566 times.
✗ Branch 1 not taken.
179566 DBUG_TRACE;
14074
14075 179566 key = form->key_info + key_num;
14076
14077 /* Assert that "GEN_CLUST_INDEX" cannot be used as non-primary index */
14078
2/4
✓ Branch 0 taken 179566 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 179566 times.
179566 ut_a(innobase_strcasecmp(key->name, innobase_index_reserve_name) != 0);
14079
14080
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 179565 times.
179566 if (key->key_length == 0) {
14081
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_WRONG_KEY_COLUMN, MYF(0), key->key_part->field->field_name);
14082 1 return ER_WRONG_KEY_COLUMN;
14083 }
14084 179565 ind_type = 0;
14085
2/2
✓ Branch 0 taken 379 times.
✓ Branch 1 taken 179186 times.
179565 if (key->flags & HA_SPATIAL) {
14086 379 ind_type = DICT_SPATIAL;
14087
2/2
✓ Branch 0 taken 646 times.
✓ Branch 1 taken 178540 times.
179186 } else if (key->flags & HA_FULLTEXT) {
14088 646 ind_type = DICT_FTS;
14089 }
14090
14091
2/2
✓ Branch 0 taken 379 times.
✓ Branch 1 taken 179186 times.
179565 if (ind_type == DICT_SPATIAL) {
14092
2/2
✓ Branch 0 taken 121 times.
✓ Branch 1 taken 258 times.
379 ulint dd_index_num = key_num + ((form->s->primary_key == MAX_KEY) ? 1 : 0);
14093
14094
2/4
✓ Branch 0 taken 379 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 379 times.
✗ Branch 3 not taken.
379 const auto *dd_index_auto = dd_table->indexes()[dd_index_num];
14095
14096
1/2
✓ Branch 0 taken 379 times.
✗ Branch 1 not taken.
379 const dd::Index *dd_index = get_my_dd_index(dd_index_auto);
14097
2/4
✓ Branch 0 taken 379 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 379 times.
379 ut_ad(dd_index->name() == key->name);
14098
14099 size_t geom_col_idx;
14100
2/4
✓ Branch 0 taken 379 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 379 times.
✗ Branch 3 not taken.
379 for (geom_col_idx = 0; geom_col_idx < dd_index->elements().size();
14101 ++geom_col_idx) {
14102
5/10
✓ Branch 0 taken 379 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 379 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 379 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 379 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 379 times.
✗ Branch 9 not taken.
379 if (!dd_index->elements()[geom_col_idx]->column().is_se_hidden()) break;
14103 }
14104
3/6
✓ Branch 0 taken 379 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 379 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 379 times.
✗ Branch 5 not taken.
379 const dd::Column &col = dd_index->elements()[geom_col_idx]->column();
14105
1/2
✓ Branch 0 taken 379 times.
✗ Branch 1 not taken.
379 has_srid = col.srs_id().has_value();
14106
4/6
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 368 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 368 times.
✗ Branch 5 not taken.
379 srid = has_srid ? col.srs_id().value() : 0;
14107 }
14108
14109
2/2
✓ Branch 0 taken 1025 times.
✓ Branch 1 taken 178540 times.
179565 if (ind_type != 0) {
14110 2050 index = dict_mem_index_create(table_name, key->name, 0, ind_type,
14111
1/2
✓ Branch 0 taken 1025 times.
✗ Branch 1 not taken.
1025 key->user_defined_key_parts);
14112
14113
2/2
✓ Branch 0 taken 1157 times.
✓ Branch 1 taken 1025 times.
2182 for (ulint i = 0; i < key->user_defined_key_parts; i++) {
14114 1157 KEY_PART_INFO *key_part = key->key_part + i;
14115
14116 /* We do not support special (Fulltext or Spatial)
14117 index on virtual columns */
14118
3/4
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 1111 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 46 times.
1157 if (innobase_is_v_fld(key_part->field)) {
14119 ut_d(ut_error);
14120 ut_o(return HA_ERR_UNSUPPORTED);
14121 }
14122
14123 1157 index->add_field(key_part->field->field_name, 0,
14124
1/2
✓ Branch 0 taken 1157 times.
✗ Branch 1 not taken.
1157 !(key_part->key_part_flag & HA_REVERSE_SORT));
14125 }
14126
14127
2/2
✓ Branch 0 taken 379 times.
✓ Branch 1 taken 646 times.
1025 if (ind_type == DICT_SPATIAL) {
14128 379 index->srid_is_valid = has_srid;
14129 379 index->srid = srid;
14130
1/2
✓ Branch 0 taken 379 times.
✗ Branch 1 not taken.
379 index->rtr_srs.reset(fetch_srs(index->srid));
14131 }
14132
14133
2/4
✓ Branch 0 taken 1025 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1025 times.
✗ Branch 3 not taken.
1025 return convert_error_code_to_mysql(
14134 row_create_index_for_mysql(index, trx, nullptr, nullptr), flags,
14135 1025 nullptr);
14136 }
14137
14138 178540 ind_type = 0;
14139
14140
2/2
✓ Branch 0 taken 105666 times.
✓ Branch 1 taken 72874 times.
178540 if (key_num == form->s->primary_key) {
14141 105666 ind_type |= DICT_CLUSTERED;
14142 }
14143
14144
2/2
✓ Branch 0 taken 139878 times.
✓ Branch 1 taken 38662 times.
178540 if (key->flags & HA_NOSAME) {
14145 139878 ind_type |= DICT_UNIQUE;
14146 }
14147
14148 357080 field_lengths = (ulint *)my_malloc(
14149
1/2
✓ Branch 0 taken 178540 times.
✗ Branch 1 not taken.
178540 PSI_INSTRUMENT_ME, key->user_defined_key_parts * sizeof *field_lengths,
14150 MYF(MY_FAE));
14151
14152 /* We pass 0 as the space id, and determine at a lower level the space
14153 id where to store the table */
14154
14155 357080 index = dict_mem_index_create(table_name, key->name, 0, ind_type,
14156
1/2
✓ Branch 0 taken 178540 times.
✗ Branch 1 not taken.
178540 key->user_defined_key_parts);
14157
14158
1/2
✓ Branch 0 taken 178540 times.
✗ Branch 1 not taken.
178540 innodb_session_t *&priv = thd_to_innodb_session(trx->mysql_thd);
14159
1/2
✓ Branch 0 taken 178539 times.
✗ Branch 1 not taken.
178540 dict_table_t *handler = priv->lookup_table_handler(table_name);
14160
14161
2/2
✓ Branch 0 taken 2811 times.
✓ Branch 1 taken 175728 times.
178539 if (handler != nullptr) {
14162 /* This setting will enforce SQL NULL == SQL NULL.
14163 For now this is turned-on for intrinsic tables
14164 only but can be turned on for other tables if needed arises. */
14165 2811 index->nulls_equal = (key->flags & HA_NULL_ARE_EQUAL) ? true : false;
14166
14167 /* Disable use of AHI for intrinsic table indexes as AHI
14168 validates the predicated entry using index-id which has to be
14169 system-wide unique that is not the case with indexes of
14170 intrinsic table for performance reason.
14171 Also given the lifetime of these tables and frequent delete
14172 and update AHI would not help on performance front as it does
14173 with normal tables. */
14174 2811 index->disable_ahi = true;
14175 }
14176
14177
2/2
✓ Branch 0 taken 248182 times.
✓ Branch 1 taken 178540 times.
426722 for (ulint i = 0; i < key->user_defined_key_parts; i++) {
14178 248182 KEY_PART_INFO *key_part = key->key_part + i;
14179 ulint prefix_len;
14180 ulint col_type;
14181 ulint is_unsigned;
14182
14183 /* (The flag HA_PART_KEY_SEG denotes in MySQL a
14184 column prefix field in an index: we only store a
14185 specified number of first bytes of the column to
14186 the index field.) The flag does not seem to be
14187 properly set by MySQL. Let us fall back on testing
14188 the length of the key part versus the column.
14189 We first reach to the table's column; if the index is on a
14190 prefix, key_part->field is not the table's column (it's a
14191 "fake" field forged in open_table_from_share() with length
14192 equal to the length of the prefix); so we have to go to
14193 form->fied. */
14194 248182 Field *field = form->field[key_part->field->field_index()];
14195
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 248183 times.
248183 if (field == nullptr) ut_error;
14196
14197 248183 const char *field_name = key_part->field->field_name;
14198
6/8
✓ Branch 0 taken 3545 times.
✓ Branch 1 taken 244638 times.
✓ Branch 2 taken 3545 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3545 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3545 times.
✓ Branch 7 taken 244638 times.
248183 if (handler != nullptr && handler->is_intrinsic()) {
14199
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 3545 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3545 times.
3545 ut_ad(!innobase_is_v_fld(key_part->field));
14200 ulint col_no =
14201
2/4
✓ Branch 0 taken 3545 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3545 times.
✗ Branch 3 not taken.
3545 dict_col_get_no(handler->get_col(key_part->field->field_index()));
14202
1/2
✓ Branch 0 taken 3545 times.
✗ Branch 1 not taken.
3545 field_name = handler->get_col_name(col_no);
14203 }
14204
14205
1/2
✓ Branch 0 taken 248182 times.
✗ Branch 1 not taken.
248183 col_type = get_innobase_type_from_mysql_type(&is_unsigned, key_part->field);
14206
14207 /* Multi-value prefix index is not supported. */
14208
7/8
✓ Branch 0 taken 248182 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 247939 times.
✓ Branch 3 taken 243 times.
✓ Branch 4 taken 242894 times.
✓ Branch 5 taken 5046 times.
✓ Branch 6 taken 6072 times.
✓ Branch 7 taken 242110 times.
739015 if (!innobase_is_multi_value_fld(key_part->field) &&
14209 247939 (DATA_LARGE_MTYPE(col_type) ||
14210
3/4
✓ Branch 0 taken 242893 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37530 times.
✓ Branch 3 taken 205363 times.
242894 (key_part->length < field->pack_length() &&
14211
3/4
✓ Branch 0 taken 37530 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37011 times.
✓ Branch 3 taken 519 times.
37530 field->type() != MYSQL_TYPE_VARCHAR) ||
14212
3/4
✓ Branch 0 taken 242374 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37011 times.
✓ Branch 3 taken 205363 times.
242374 (field->type() == MYSQL_TYPE_VARCHAR &&
14213 37011 key_part->length <
14214
4/6
✓ Branch 0 taken 37011 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37011 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 507 times.
✓ Branch 5 taken 36504 times.
37011 field->pack_length() - field->get_length_bytes()))) {
14215
1/2
✓ Branch 0 taken 6072 times.
✗ Branch 1 not taken.
6072 switch (col_type) {
14216 6072 default:
14217 6072 prefix_len = key_part->length;
14218 6072 break;
14219 case DATA_INT:
14220 case DATA_FLOAT:
14221 case DATA_DOUBLE:
14222 case DATA_DECIMAL:
14223 log_errlog(ERROR_LEVEL, ER_WRONG_TYPE_FOR_COLUMN_PREFIX_IDX_FLD,
14224 table_name, key_part->field->field_name);
14225
14226 prefix_len = 0;
14227 }
14228 } else {
14229 242110 prefix_len = 0;
14230 }
14231
14232 248182 field_lengths[i] = key_part->length;
14233
14234
7/10
✓ Branch 0 taken 5420 times.
✓ Branch 1 taken 242762 times.
✓ Branch 2 taken 1029 times.
✓ Branch 3 taken 4391 times.
✓ Branch 4 taken 243792 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 243792 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 248183 times.
248182 ut_ad(!(!innobase_is_v_fld(key_part->field) &&
14235 innobase_is_multi_value_fld(key_part->field)));
14236
14237
4/4
✓ Branch 0 taken 5420 times.
✓ Branch 1 taken 242763 times.
✓ Branch 2 taken 4391 times.
✓ Branch 3 taken 1029 times.
248183 if (innobase_is_v_fld(key_part->field)) {
14238 4391 index->type |= DICT_VIRTUAL;
14239
14240
3/4
✓ Branch 0 taken 4391 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 243 times.
✓ Branch 3 taken 4148 times.
4391 if (innobase_is_multi_value_fld(key_part->field)) {
14241 243 index->type |= DICT_MULTI_VALUE;
14242 }
14243 }
14244
14245 248183 index->add_field(field_name, prefix_len,
14246
1/2
✓ Branch 0 taken 248183 times.
✗ Branch 1 not taken.
248183 !(key_part->key_part_flag & HA_REVERSE_SORT));
14247 }
14248
14249
3/6
✓ Branch 0 taken 178540 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 178540 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 178540 times.
178540 ut_ad(key->flags & HA_FULLTEXT || !(index->type & DICT_FTS));
14250
14251 178540 multi_val_idx = ((index->type & DICT_MULTI_VALUE) == DICT_MULTI_VALUE);
14252
14253 /* Even though we've defined max_supported_key_part_length, we
14254 still do our own checking using field_lengths to be absolutely
14255 sure we don't create too long indexes. */
14256
14257
2/4
✓ Branch 0 taken 178457 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 178457 times.
✗ Branch 3 not taken.
178540 error = convert_error_code_to_mysql(
14258 row_create_index_for_mysql(index, trx, field_lengths, handler), flags,
14259 nullptr);
14260
14261 /* For multi-value virtual index, we need to adjust indexed col length */
14262
4/4
✓ Branch 0 taken 178444 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 243 times.
✓ Branch 3 taken 178201 times.
178457 if (error == 0 && multi_val_idx) {
14263
1/2
✓ Branch 0 taken 243 times.
✗ Branch 1 not taken.
243 dict_table_t *new_table = dd_table_open_on_name_in_mem(table_name, false);
14264
14265 243 dict_index_t *last_index = UT_LIST_GET_LAST(new_table->indexes);
14266
2/2
✓ Branch 0 taken 523 times.
✓ Branch 1 taken 243 times.
766 for (unsigned int i = 0; i < last_index->n_fields; i++) {
14267
4/4
✓ Branch 0 taken 243 times.
✓ Branch 1 taken 280 times.
✓ Branch 2 taken 161 times.
✓ Branch 3 taken 362 times.
766 if (last_index->fields[i].col->is_multi_value() &&
14268
2/2
✓ Branch 0 taken 161 times.
✓ Branch 1 taken 82 times.
243 (last_index->fields[i].fixed_len != 0)) {
14269 161 last_index->fields[i].fixed_len = field_lengths[i];
14270 }
14271 }
14272
14273
1/2
✓ Branch 0 taken 243 times.
✗ Branch 1 not taken.
243 dd_table_close(new_table, nullptr, nullptr, false);
14274 }
14275
14276
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 178444 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
178457 if (error && handler != nullptr) {
14277 priv->unregister_table_handler(table_name);
14278 }
14279
14280
1/2
✓ Branch 0 taken 178457 times.
✗ Branch 1 not taken.
178457 my_free(field_lengths);
14281
14282 178457 return error;
14283 179483 }
14284
14285 /** Creates an index to an InnoDB table when the user has defined no
14286 primary index. */
14287 242444 inline int create_clustered_index_when_no_primary(
14288 trx_t *trx, /*!< in: InnoDB transaction handle */
14289 uint32_t flags, /*!< in: InnoDB table flags */
14290 const char *table_name) /*!< in: table name */
14291 {
14292 dict_index_t *index;
14293 dberr_t error;
14294
14295 /* We pass 0 as the space id, and determine at a lower level the space
14296 id where to store the table */
14297 242444 index = dict_mem_index_create(table_name, innobase_index_reserve_name, 0,
14298 DICT_CLUSTERED, 0);
14299
14300 242444 innodb_session_t *&priv = thd_to_innodb_session(trx->mysql_thd);
14301
14302 242444 dict_table_t *handler = priv->lookup_table_handler(table_name);
14303
14304
2/2
✓ Branch 0 taken 110275 times.
✓ Branch 1 taken 132169 times.
242444 if (handler != nullptr) {
14305 /* Disable use of AHI for intrinsic table indexes as AHI
14306 validates the predicated entry using index-id which has to be
14307 system-wide unique that is not the case with indexes of
14308 intrinsic table for performance reason.
14309 Also given the lifetime of these tables and frequent delete
14310 and update AHI would not help on performance front as it does
14311 with normal tables. */
14312 110275 index->disable_ahi = true;
14313 }
14314
14315 242444 error = row_create_index_for_mysql(index, trx, nullptr, handler);
14316
14317
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 242431 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
242444 if (error != DB_SUCCESS && handler != nullptr) {
14318 priv->unregister_table_handler(table_name);
14319 }
14320
14321 242444 return (convert_error_code_to_mysql(error, flags, nullptr));
14322 }
14323
14324 26 void create_table_info_t::log_error_invalid_location(std::string &msg,
14325 bool ignore) {
14326
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 18 times.
26 if (ignore) {
14327
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 THD *thd = current_thd;
14328
14329 8 constexpr char ignored_msg[] =
14330 " The DATA DIRECTORY location will be ignored and the"
14331 " file will be put into the default datadir location.";
14332
14333
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 msg.append(ignored_msg);
14334
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_FILE_NAME,
14335 "%s", msg.c_str());
14336
14337
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 ib::warn(ER_IB_MSG_INVALID_LOCATION_FOR_TABLE, m_table_name, msg.c_str());
14338 } else {
14339 18 my_printf_error(ER_WRONG_FILE_NAME, "%s", MYF(0), msg.c_str());
14340
14341
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 ib::error(ER_IB_MSG_INVALID_LOCATION_FOR_TABLE, m_table_name, msg.c_str());
14342 }
14343 26 }
14344
14345 878 bool create_table_info_t::create_option_data_directory_is_valid(bool ignore) {
14346 878 bool is_valid = true;
14347
14348
3/6
✓ Branch 0 taken 878 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 878 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 878 times.
878 ut_ad(m_create_info->data_file_name != nullptr &&
14349 *m_create_info->data_file_name != '\0');
14350
14351 /* Use DATA DIRECTORY only with file-per-table. */
14352
3/4
✓ Branch 0 taken 878 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 870 times.
878 if (!m_use_shared_space && !m_allow_file_per_table) {
14353
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 push_warning(m_thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION,
14354 "InnoDB: DATA DIRECTORY requires"
14355 " innodb_file_per_table.");
14356 8 is_valid = false;
14357 }
14358
14359 /* Do not use DATA DIRECTORY with TEMPORARY TABLE. */
14360
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 872 times.
878 if (m_create_info->options & HA_LEX_CREATE_TMP_TABLE) {
14361
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 push_warning(m_thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION,
14362 "InnoDB: DATA DIRECTORY cannot be used"
14363 " for TEMPORARY tables.");
14364 6 is_valid = false;
14365 }
14366
14367 /* We checked previously for a conflicting DATA DIRECTORY mixed
14368 with TABLESPACE in create_option_tablespace_is_valid().
14369 An ALTER TABLE statement might have both if it is being moved.
14370 So if m_tablespace is set, don't check the existing data_file_name. */
14371
2/2
✓ Branch 0 taken 192 times.
✓ Branch 1 taken 686 times.
878 if (m_create_info->tablespace != nullptr) {
14372 192 return (is_valid);
14373 }
14374
14375 #ifndef UNIV_HOTBACKUP
14376 /* Validate the directory location. */
14377 686 bool suffixed_table_name = !m_partition;
14378
3/6
✓ Branch 0 taken 686 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 686 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 686 times.
✗ Branch 5 not taken.
686 char *filepath = Fil_path::make(m_create_info->data_file_name, m_table_name,
14379 IBD, suffixed_table_name);
14380
1/2
✓ Branch 0 taken 686 times.
✗ Branch 1 not taken.
686 size_t dirname_len = dirname_length(filepath);
14381
1/2
✓ Branch 0 taken 686 times.
✗ Branch 1 not taken.
686 Fil_path dirpath(filepath, dirname_len, true);
14382
14383 /* Do not allow the file to be created in a unique undo directory. */
14384
6/8
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 643 times.
✓ Branch 2 taken 43 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 43 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 683 times.
729 if (MySQL_undo_path_is_unique && (MySQL_undo_path.is_same_as(dirpath) ||
14385
3/4
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 40 times.
43 MySQL_undo_path.is_ancestor(dirpath))) {
14386 std::string msg(
14387
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 "The DATA DIRECTORY location cannot be the undo directory.");
14388
14389
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 log_error_invalid_location(msg, ignore);
14390
14391 3 is_valid = false;
14392 3 }
14393
14394 /* Do not allow a file-per-table tablespace in the datadir.
14395 In order to be located in the datadir, one must use a schama name
14396 identical to the datadir directory and the datadir parent must be
14397 used as the DATA DIRECTORY.*/
14398
1/2
✓ Branch 0 taken 686 times.
✗ Branch 1 not taken.
686 bool in_datadir = MySQL_datadir_path.is_same_as(dirpath);
14399
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 684 times.
686 if (in_datadir) {
14400
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 std::string msg("The DATA DIRECTORY location cannot be the datadir.");
14401
14402
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 log_error_invalid_location(msg, ignore);
14403
14404 2 is_valid = false;
14405 2 }
14406
14407 /* Do not allow a datafile outside the known directories. */
14408
1/2
✓ Branch 0 taken 686 times.
✗ Branch 1 not taken.
686 bool under_datadir = MySQL_datadir_path.is_ancestor(dirpath);
14409 bool in_known_location =
14410
6/8
✓ Branch 0 taken 684 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 684 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 684 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 663 times.
✓ Branch 7 taken 21 times.
686 (in_datadir || under_datadir) ? true : fil_path_is_known(dirpath.path());
14411
14412
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 665 times.
686 if (!in_known_location) {
14413 std::string msg(
14414
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 "The DATA DIRECTORY location must be in a known directory.");
14415
14416
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 log_error_invalid_location(msg, ignore);
14417
14418 21 is_valid = false;
14419 21 }
14420
14421 686 ut::free(filepath);
14422 #endif /* UNIV_HOTBACKUP */
14423
14424 686 return (is_valid);
14425 686 }
14426
14427 /** Validate the tablespace name provided for a tablespace DDL
14428 @param[in] ts_command tablespace command type
14429 @param[in] name A proposed tablespace name
14430 @return MySQL handler error code like HA_... */
14431 420289 static int validate_tablespace_name(ts_command_type ts_command,
14432 const char *name) {
14433 420289 int err = 0;
14434
14435 /* This prefix is reserved by InnoDB for use in internal tablespace
14436 names. */
14437 420289 const char reserved_space_name_prefix[] = "innodb_";
14438
14439 /* Validation at the SQL layer should already be completed at this
14440 stage. Re-assert that the length is valid. */
14441
2/4
✓ Branch 0 taken 420289 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 420289 times.
420289 if (validate_tablespace_name_length(name)) {
14442 my_printf_error(ER_WRONG_TABLESPACE_NAME,
14443 "InnoDB: Tablespace name `%s` is too long.", MYF(0), name);
14444 return (HA_WRONG_CREATE_OPTION);
14445 }
14446
14447 /* The tablespace name cannot start with `innodb_`. */
14448
2/2
✓ Branch 0 taken 21888 times.
✓ Branch 1 taken 398401 times.
420289 if (strlen(name) >= sizeof(reserved_space_name_prefix) - 1 &&
14449
2/2
✓ Branch 0 taken 1976 times.
✓ Branch 1 taken 19912 times.
21888 0 == memcmp(name, reserved_space_name_prefix,
14450 sizeof(reserved_space_name_prefix) - 1)) {
14451 /* Use a different message for reserved names */
14452
2/2
✓ Branch 0 taken 1032 times.
✓ Branch 1 taken 944 times.
1976 if (0 == strcmp(name, dict_sys_t::s_file_per_table_name) ||
14453
2/2
✓ Branch 0 taken 308 times.
✓ Branch 1 taken 724 times.
1032 0 == strcmp(name, dict_sys_t::s_sys_space_name) ||
14454
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 271 times.
308 0 == strcmp(name, dict_sys_t::s_temp_space_name)) {
14455 /* Allow these names if the caller is putting a
14456 table into one of these by CREATE/ALTER TABLE */
14457
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 1688 times.
1705 if (ts_command != TS_CMD_NOT_DEFINED) {
14458
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 my_printf_error(ER_WRONG_TABLESPACE_NAME,
14459 "InnoDB: `%s` is a reserved"
14460 " tablespace name.",
14461 MYF(0), name);
14462 17 err = HA_WRONG_CREATE_OPTION;
14463 }
14464 } else {
14465 /* Allow any undo tablespace to be set active or inactive.
14466 And any undo tablespace can be dropped except the default two
14467 implicit spaces. All other DDL should not work on tablespaces
14468 that start with "innodb_". */
14469 271 bool allow =
14470
4/4
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 244 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 20 times.
278 (ts_command == ALTER_UNDO_TABLESPACE ||
14471 7 (ts_command == DROP_UNDO_TABLESPACE &&
14472
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 0 != strcmp(name, dict_sys_t::s_default_undo_space_name_1) &&
14473 0 != strcmp(name, dict_sys_t::s_default_undo_space_name_2)));
14474
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 244 times.
271 if (!allow) {
14475
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 my_printf_error(ER_WRONG_TABLESPACE_NAME,
14476 "InnoDB: Tablespace names starting"
14477 " with `%s` are reserved.",
14478 MYF(0), reserved_space_name_prefix);
14479 27 err = HA_WRONG_CREATE_OPTION;
14480 }
14481 }
14482
2/2
✓ Branch 0 taken 392483 times.
✓ Branch 1 taken 25830 times.
420289 } else if (0 == strcmp(name, dict_sys_t::s_dd_space_name)) {
14483 /* mysql tablespace can't be created or dropped */
14484
4/4
✓ Branch 0 taken 392479 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 392472 times.
392483 if (ts_command == CREATE_TABLESPACE || ts_command == DROP_TABLESPACE) {
14485
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 my_printf_error(ER_WRONG_TABLESPACE_NAME,
14486 "InnoDB: `mysql` is a reserved"
14487 " tablespace name.",
14488 MYF(0));
14489 11 err = HA_WRONG_CREATE_OPTION;
14490 }
14491 }
14492
14493 /* The tablespace name cannot contain a '/'. */
14494
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 420282 times.
420289 if (memchr(name, '/', strlen(name)) != nullptr) {
14495
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 my_printf_error(ER_WRONG_TABLESPACE_NAME,
14496 "InnoDB: A general tablespace name cannot"
14497 " contain '/'.",
14498 MYF(0));
14499 7 err = HA_WRONG_CREATE_OPTION;
14500 }
14501
14502 420289 return (err);
14503 }
14504
14505 362424 bool innobase_is_valid_tablespace_name(ts_command_type ts_cmd,
14506 const char *name) {
14507 362424 return (0 == validate_tablespace_name(ts_cmd, name));
14508 }
14509
14510 /** Validate TABLESPACE option.
14511 @return true if valid, false if not. */
14512 381168 bool create_table_info_t::create_option_tablespace_is_valid() {
14513 381168 bool is_temp = m_create_info->options & HA_LEX_CREATE_TMP_TABLE;
14514 381168 bool is_file_per_table = tablespace_is_file_per_table(m_create_info);
14515 381168 bool is_general_space = tablespace_is_general_space(m_create_info);
14516 381168 bool is_temp_space =
14517
2/2
✓ Branch 0 taken 71267 times.
✓ Branch 1 taken 309901 times.
452435 (m_create_info->tablespace &&
14518
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 71250 times.
71267 strcmp(m_create_info->tablespace, dict_sys_t::s_temp_space_name) == 0);
14519
14520 /* Do not allow creation of a temp table
14521 with innodb_file_per_table or innodb_temporary option. */
14522
6/6
✓ Branch 0 taken 153562 times.
✓ Branch 1 taken 227606 times.
✓ Branch 2 taken 153560 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 153547 times.
381168 if (is_temp && (is_file_per_table || is_temp_space)) {
14523
7/8
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 14 times.
15 if (THDVAR(m_thd, strict_mode) && is_file_per_table) {
14524 1 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
14525 "InnoDB: TABLESPACE=%s option"
14526 " is disallowed for temporary tables"
14527 " with INNODB_STRICT_MODE=ON. This option is"
14528 " deprecated and will be removed in a future release",
14529
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 MYF(0), m_create_info->tablespace);
14530 1 return false;
14531 }
14532
14533 /* STRICT mode turned off. Proceed with the execution with
14534 a deprecation warning */
14535 14 push_warning_printf(
14536 m_thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION,
14537 "InnoDB: TABLESPACE=%s option is ignored. All temporary tables"
14538 " are created in a session temporary tablespace. This option"
14539 " is deprecated and will be removed in a future release.",
14540
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 m_create_info->tablespace);
14541 }
14542
14543 /* Check the encryption option validity. */
14544
6/6
✓ Branch 0 taken 69374 times.
✓ Branch 1 taken 311793 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 69364 times.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 381157 times.
450541 if (m_create_info->encrypt_type.str != nullptr &&
14545 69374 Encryption::validate(m_create_info->encrypt_type.str) == DB_UNSUPPORTED) {
14546
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 my_error(ER_INVALID_ENCRYPTION_OPTION, MYF(0));
14547 10 return false;
14548 }
14549
14550
2/2
✓ Branch 0 taken 337659 times.
✓ Branch 1 taken 43498 times.
381157 if (!m_use_shared_space) {
14551
2/2
✓ Branch 0 taken 158080 times.
✓ Branch 1 taken 179579 times.
337659 if (!m_use_file_per_table) {
14552
2/2
✓ Branch 0 taken 1123 times.
✓ Branch 1 taken 156957 times.
158080 if (m_create_info->encrypt_type.str != nullptr &&
14553
4/4
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 1103 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 11 times.
1123 m_create_info->explicit_encryption && is_temp) {
14554 /* Temporary tablespace is being used for table */
14555
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
14556 "InnoDB: ENCRYPTION is not accepted"
14557 " for temporary tablespace. For temporary tablespace"
14558 " encryption please use innodb_temp_tablespace_encrypt"
14559 " variable.",
14560 MYF(0));
14561 9 return false;
14562 }
14563
14564
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 158070 times.
158071 if (m_create_info->m_implicit_tablespace_autoextend_size > 0) {
14565 /* AUTOEXTEND_SIZE is not allowed for system tablespace. */
14566
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
14567 "InnoDB : AUTOEXTEND_SIZE is not accepted"
14568 " for system tablespace.",
14569 MYF(0));
14570 1 return false;
14571 }
14572 }
14573
14574 /* Validate autoextend_size attribute value. */
14575
4/4
✓ Branch 0 taken 5510 times.
✓ Branch 1 taken 332139 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 337635 times.
343159 if (m_create_info->m_implicit_tablespace_autoextend_size > 0 &&
14576
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 5496 times.
5510 validate_autoextend_size_value(
14577
1/2
✓ Branch 0 taken 5510 times.
✗ Branch 1 not taken.
5510 m_create_info->m_implicit_tablespace_autoextend_size) !=
14578 DB_SUCCESS) {
14579 14 return false;
14580 }
14581 337635 return true;
14582 }
14583
14584
3/4
✓ Branch 0 taken 43498 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 360 times.
✓ Branch 3 taken 43138 times.
43498 if (m_use_shared_space && !is_general_space) {
14585
2/2
✓ Branch 0 taken 231 times.
✓ Branch 1 taken 129 times.
360 if (m_create_info->m_implicit_tablespace_autoextend_size_change &&
14586
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 230 times.
231 m_create_info->m_implicit_tablespace_autoextend_size > 0) {
14587 /* AUTOEXTEND_SIZE is not allowed for system tablespace. */
14588
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
14589 "InnoDB : AUTOEXTEND_SIZE is not accepted"
14590 " for system tablespace.",
14591 MYF(0));
14592 1 return false;
14593 }
14594 }
14595
14596 /* ALTER TABLE ... AUTOEXTEND_SIZE is not allowed if the tablespace is
14597 a general tablespace. */
14598
5/6
✓ Branch 0 taken 43480 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 43135 times.
✓ Branch 3 taken 345 times.
✓ Branch 4 taken 43135 times.
✗ Branch 5 not taken.
43497 if (!is_temp && is_general_space && m_use_shared_space) {
14599
2/2
✓ Branch 0 taken 21576 times.
✓ Branch 1 taken 21559 times.
43135 if (m_create_info->m_implicit_tablespace_autoextend_size_change &&
14600
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 21570 times.
21576 m_create_info->m_implicit_tablespace_autoextend_size > 0) {
14601
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_error(ER_INNODB_INCOMPATIBLE_WITH_TABLESPACE, MYF(0),
14602 "AUTOEXTEND_SIZE");
14603 6 return false;
14604 }
14605 }
14606
14607 /* Validate autoextend_size attribute value. */
14608
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 43489 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 43491 times.
43493 if (m_create_info->m_implicit_tablespace_autoextend_size > 0 &&
14609
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 validate_autoextend_size_value(
14610
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 m_create_info->m_implicit_tablespace_autoextend_size) != DB_SUCCESS) {
14611 return false;
14612 }
14613
14614 /* Name validation should be ensured from the SQL layer. */
14615
2/4
✓ Branch 0 taken 43491 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 43491 times.
43491 ut_ad(0 == validate_tablespace_name(TS_CMD_NOT_DEFINED,
14616 m_create_info->tablespace));
14617
14618 /* Look up the tablespace name in the fil_system. */
14619
1/2
✓ Branch 0 taken 43491 times.
✗ Branch 1 not taken.
43491 space_id_t space_id = fil_space_get_id_by_name(m_create_info->tablespace);
14620
14621
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 43489 times.
43491 if (space_id == SPACE_UNKNOWN) {
14622 2 my_printf_error(ER_TABLESPACE_MISSING,
14623 "InnoDB: A general tablespace named"
14624 " `%s` cannot be found.",
14625
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 MYF(0), m_create_info->tablespace);
14626 2 return false;
14627 }
14628
14629
3/4
✓ Branch 0 taken 43489 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 43487 times.
43489 if (fsp_is_undo_tablespace(space_id)) {
14630
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_printf_error(ER_WRONG_TABLESPACE_NAME,
14631 "InnoDB: An undo tablespace cannot contain tables.",
14632 MYF(0));
14633
14634 2 return false;
14635 }
14636
14637 /* Cannot add a second table to a file-per-table tablespace. */
14638
1/2
✓ Branch 0 taken 43487 times.
✗ Branch 1 not taken.
43487 uint32_t fsp_flags = fil_space_get_flags(space_id);
14639
2/4
✓ Branch 0 taken 43487 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 43487 times.
43487 if (fsp_is_file_per_table(space_id, fsp_flags)) {
14640 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
14641 "InnoDB: Tablespace `%s` is file-per-table so no"
14642 " other table can be added to it.",
14643 MYF(0), m_create_info->tablespace);
14644 return false;
14645 }
14646
14647
1/2
✓ Branch 0 taken 43487 times.
✗ Branch 1 not taken.
43487 bool is_create_table = (thd_sql_command(m_thd) == SQLCOM_CREATE_TABLE);
14648
14649 /* If TABLESPACE=innodb_file_per_table this function is not called
14650 since tablespace_is_shared_space() will return false. Any other
14651 tablespace is incompatible with the DATA DIRECTORY phrase.
14652 On any ALTER TABLE that contains a DATA DIRECTORY, MySQL will issue
14653 a warning like "<DATA DIRECTORY> option ignored." The check below is
14654 needed for CREATE TABLE only. ALTER TABLE may be moving remote
14655 file-per-table table to a general tablespace, in which case the
14656 create_info->data_file_name is not null. */
14657
4/4
✓ Branch 0 taken 20266 times.
✓ Branch 1 taken 23221 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 20264 times.
43487 if (is_create_table && m_create_info->data_file_name != nullptr &&
14658
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 *m_create_info->data_file_name != '\0') {
14659
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
14660 "InnoDB: DATA DIRECTORY cannot be used"
14661 " with a TABLESPACE assignment.",
14662 MYF(0));
14663 2 return false;
14664 }
14665
14666 /* Temp tables only belong in temp tablespaces. */
14667
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 43468 times.
43485 if (m_create_info->options & HA_LEX_CREATE_TMP_TABLE) {
14668
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 13 times.
17 if (!FSP_FLAGS_GET_TEMPORARY(fsp_flags)) {
14669 4 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
14670 "InnoDB: Tablespace `%s` cannot contain"
14671 " TEMPORARY tables.",
14672
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 MYF(0), m_create_info->tablespace);
14673 4 return false;
14674 }
14675
14676 /* Restrict Compressed Temporary General tablespaces. */
14677
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 if (m_create_info->key_block_size ||
14678
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12 times.
13 m_create_info->row_type == ROW_TYPE_COMPRESSED) {
14679 1 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
14680 "InnoDB: Temporary tablespace `%s` cannot"
14681 " contain COMPRESSED tables.",
14682
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 MYF(0), m_create_info->tablespace);
14683 1 return false;
14684 }
14685
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 43464 times.
43468 } else if (FSP_FLAGS_GET_TEMPORARY(fsp_flags)) {
14686 4 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
14687 "InnoDB: Tablespace `%s` can only contain"
14688 " TEMPORARY tables.",
14689
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 MYF(0), m_create_info->tablespace);
14690 4 return false;
14691 }
14692
14693 /* Make sure the physical page size of the table matches the
14694 file block size of the tablespace. */
14695 ulint block_size_needed;
14696 bool table_is_compressed;
14697
2/2
✓ Branch 0 taken 119 times.
✓ Branch 1 taken 43357 times.
43476 if (m_create_info->key_block_size) {
14698 119 block_size_needed = m_create_info->key_block_size * 1024;
14699 119 table_is_compressed = true;
14700
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 43349 times.
43357 } else if (m_create_info->row_type == ROW_TYPE_COMPRESSED) {
14701 8 block_size_needed =
14702 8 std::min(UNIV_PAGE_SIZE / 2, static_cast<ulint>(UNIV_ZIP_SIZE_MAX));
14703 8 table_is_compressed = true;
14704 } else {
14705 43349 block_size_needed = UNIV_PAGE_SIZE;
14706 43349 table_is_compressed = false;
14707 }
14708
14709
1/2
✓ Branch 0 taken 43476 times.
✗ Branch 1 not taken.
43476 const page_size_t page_size(fsp_flags);
14710
14711 /* The compression code needs some work in order for a general
14712 tablespace to contain both compressed and non-compressed tables
14713 together in the same tablespace. The problem seems to be that
14714 each page is either compressed or not based on the fsp flags,
14715 which is shared by all tables in that general tablespace. */
14716
7/8
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 43349 times.
✓ Branch 2 taken 127 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 29 times.
✓ Branch 5 taken 98 times.
✓ Branch 6 taken 29 times.
✓ Branch 7 taken 43447 times.
43476 if (table_is_compressed && page_size.physical() == UNIV_PAGE_SIZE) {
14717 29 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
14718 "InnoDB: Tablespace `%s` cannot contain a"
14719 " COMPRESSED table",
14720
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 MYF(0), m_create_info->tablespace);
14721 29 return false;
14722 }
14723
14724
3/4
✓ Branch 0 taken 43447 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 76 times.
✓ Branch 3 taken 43371 times.
43447 if (block_size_needed != page_size.physical()) {
14725
1/2
✓ Branch 0 taken 76 times.
✗ Branch 1 not taken.
76 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
14726 "InnoDB: Tablespace `%s` uses block size %zu"
14727 " and cannot contain a table with physical"
14728 " page size " ULINTPF,
14729
1/2
✓ Branch 0 taken 76 times.
✗ Branch 1 not taken.
76 MYF(0), m_create_info->tablespace, page_size.physical(),
14730 block_size_needed);
14731 76 return false;
14732 }
14733
14734 43371 return true;
14735 }
14736
14737 /** Validate the COPMRESSION option.
14738 @return true if valid, false if not. */
14739 761286 bool create_table_info_t::create_option_compression_is_valid() {
14740 dberr_t err;
14741 761286 Compression compression;
14742
14743
2/2
✓ Branch 0 taken 760984 times.
✓ Branch 1 taken 303 times.
761287 if (m_create_info->compress.length == 0) {
14744 760984 return (true);
14745 }
14746
14747
1/2
✓ Branch 0 taken 303 times.
✗ Branch 1 not taken.
303 err = Compression::check(m_create_info->compress.str, &compression);
14748
14749
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 297 times.
303 if (err == DB_UNSUPPORTED) {
14750 6 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
14751 ER_UNSUPPORTED_EXTENSION,
14752 "InnoDB: Unsupported compression algorithm '%s'",
14753
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 m_create_info->compress.str);
14754 6 return (false);
14755 }
14756
14757 /* Allow Compression=NONE on any tablespace or row format. */
14758
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 225 times.
297 if (compression.m_type == Compression::NONE) {
14759 72 return (true);
14760 }
14761
14762 static char intro[] = "InnoDB: Page Compression is not supported";
14763
14764
2/2
✓ Branch 0 taken 221 times.
✓ Branch 1 taken 4 times.
225 if (m_create_info->key_block_size != 0 ||
14765
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 215 times.
221 m_create_info->row_type == ROW_TYPE_COMPRESSED) {
14766
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
14767 ER_UNSUPPORTED_EXTENSION,
14768 "%s with row_format=compressed or"
14769 " key_block_size > 0",
14770 intro);
14771 10 return (false);
14772 }
14773
14774
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 210 times.
215 if (m_create_info->options & HA_LEX_CREATE_TMP_TABLE) {
14775
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 push_warning_printf(m_thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED,
14776 "%s for temporary tables", intro);
14777 5 return (false);
14778 }
14779
14780
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 204 times.
210 if (tablespace_is_general_space(m_create_info)) {
14781
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 push_warning_printf(m_thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED,
14782 "%s for shared general tablespaces", intro);
14783 6 return (false);
14784 }
14785
14786 /* The only non-file-per-table tablespace left is the system space. */
14787
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 197 times.
204 if (!m_use_file_per_table) {
14788
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 push_warning_printf(m_thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED,
14789 "%s for the system tablespace", intro);
14790 7 return (false);
14791 }
14792
14793 197 return (true);
14794 }
14795
14796 /** Validate ENCRYPTION option.
14797 @return true if valid, false if not. */
14798 381006 bool create_table_info_t::create_option_encryption_is_valid() const {
14799
2/2
✓ Branch 0 taken 69271 times.
✓ Branch 1 taken 311735 times.
381006 if (m_create_info->encrypt_type.length > 0) {
14800 69271 dberr_t err = Encryption::validate(m_create_info->encrypt_type.str);
14801
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 69272 times.
69272 if (err == DB_UNSUPPORTED) {
14802 my_error(ER_INVALID_ENCRYPTION_OPTION, MYF(0));
14803 return (false);
14804 }
14805 }
14806
14807 bool table_is_keyring =
14808 381007 Encryption::is_keyring(m_create_info->encrypt_type.str);
14809
14810
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 381007 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
381007 if (table_is_keyring && !m_allow_file_per_table) {
14811 my_printf_error(ER_KEYRING_ILLEGAL_ENCRYPTION_OPTION,
14812 "InnoDB: KEYRING requires innodb_file_per_table.", MYF(0));
14813 return (false);
14814 }
14815
14816
2/2
✓ Branch 0 taken 2780 times.
✓ Branch 1 taken 378226 times.
381006 if (!table_is_keyring &&
14817
3/6
✓ Branch 0 taken 381007 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2781 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 381007 times.
762014 Encryption::is_master_key_encryption(m_create_info->encrypt_type.str) &&
14818 2780 Encryption::is_online_encryption_on()) {
14819 my_printf_error(ER_KEYRING_ILLEGAL_ENCRYPTION_OPTION,
14820 "InnoDB: ENCRYPTED='Y' not supported for table because "
14821 "online encryption to KEYRING is turned ON.",
14822 MYF(0));
14823 return (false);
14824 }
14825
14826 /* Currently we do not support keyring encryption for
14827 spatial indexes thus do not allow creating table with forced
14828 encryption */
14829
14830
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 381002 times.
381007 if (Encryption::should_be_keyring_encrypted(
14831 381007 m_create_info->explicit_encryption,
14832 381007 m_create_info->encrypt_type.str)) {
14833
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 for (ulint i = 0; i < m_form->s->keys; i++) {
14834 1 const KEY *key = m_form->key_info + i;
14835
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (key->flags & HA_SPATIAL) {
14836 my_printf_error(
14837 ER_KEYRING_ILLEGAL_ENCRYPTION_OPTION,
14838 "InnoDB: ENCRYPTED='KEYRING' not supported for table because "
14839 "it contains spatial index.",
14840 MYF(0));
14841 return (false);
14842 }
14843 }
14844 }
14845
14846 const bool table_is_encrypted =
14847 381007 !Encryption::is_none(m_create_info->encrypt_type.str);
14848
14849 ulint space_id;
14850
2/2
✓ Branch 0 taken 43371 times.
✓ Branch 1 taken 337636 times.
381007 if (m_use_shared_space) {
14851 43371 space_id = fil_space_get_id_by_name(m_create_info->tablespace);
14852
2/2
✓ Branch 0 taken 153535 times.
✓ Branch 1 taken 184101 times.
337636 } else if (m_create_info->options & HA_LEX_CREATE_TMP_TABLE) {
14853 153535 space_id = srv_tmp_space.space_id();
14854
2/2
✓ Branch 0 taken 4535 times.
✓ Branch 1 taken 179566 times.
184101 } else if (!m_use_file_per_table) {
14855 4535 space_id = TRX_SYS_SPACE;
14856 } else {
14857 179566 return (true);
14858 }
14859
14860 201441 fil_space_t *space = fil_space_get(space_id);
14861 201441 const auto fsp_flags = space->flags;
14862
14863 201441 const bool tablespace_is_encrypted = FSP_FLAGS_GET_ENCRYPTION(fsp_flags);
14864 201441 const char *const tablespace_name =
14865
2/2
✓ Branch 0 taken 46459 times.
✓ Branch 1 taken 154982 times.
201441 m_create_info->tablespace ? m_create_info->tablespace : space->name;
14866
14867
3/4
✓ Branch 0 taken 1565 times.
✓ Branch 1 taken 199876 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1565 times.
201441 if (table_is_encrypted && !tablespace_is_encrypted) {
14868 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
14869 "InnoDB: Tablespace `%s` cannot contain an"
14870 " ENCRYPTED table.",
14871 MYF(0), tablespace_name);
14872 return (false);
14873 }
14874
14875 201441 return (true);
14876 }
14877
14878 /** Validate the create options. Check that the options KEY_BLOCK_SIZE,
14879 ROW_FORMAT, DATA DIRECTORY, TEMPORARY & TABLESPACE are compatible with
14880 each other and other settings. These CREATE OPTIONS are not validated
14881 here unless innodb_strict_mode is on. With strict mode, this function
14882 will report each problem it finds using a custom message with error
14883 code ER_ILLEGAL_HA_CREATE_OPTION, not its built-in message.
14884 @return NULL if valid, string name of bad option if not. */
14885 381168 const char *create_table_info_t::create_options_are_invalid() {
14886 381168 bool has_key_block_size = (m_create_info->key_block_size != 0);
14887 381168 bool is_temp = m_create_info->options & HA_LEX_CREATE_TMP_TABLE;
14888
14889 381168 const char *ret = nullptr;
14890 381168 enum row_type row_format = m_create_info->row_type;
14891
14892
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 381169 times.
381168 ut_ad(m_thd != nullptr);
14893
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 381169 times.
381169 ut_ad(m_create_info != nullptr);
14894
14895 /* The TABLESPACE designation on a CREATE TABLE is not subject to
14896 non-strict-mode. If it is incorrect or is incompatible with other
14897 options, then we will return an error. Make sure the tablespace exists
14898 and is compatible with this table */
14899
2/2
✓ Branch 0 taken 162 times.
✓ Branch 1 taken 381006 times.
381169 if (!create_option_tablespace_is_valid()) {
14900 162 return ("TABLESPACE");
14901 }
14902
14903 /* Validate encryption parameter even if strict_mode is OFF. */
14904
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 381007 times.
381006 if (!create_option_encryption_is_valid()) return ("ENCRYPTION");
14905
14906 /* If innodb_strict_mode is not set don't do any more validation.
14907 Also, if this table is being put into a shared general tablespace
14908 we ALWAYS act like strict mode is ON.
14909 Or if caller explicitly asks for skipping strict mode check (if
14910 tablespace is not a shared general tablespace), then skip */
14911
8/8
✓ Branch 0 taken 337636 times.
✓ Branch 1 taken 43371 times.
✓ Branch 2 taken 336604 times.
✓ Branch 3 taken 1032 times.
✓ Branch 4 taken 14665 times.
✓ Branch 5 taken 321939 times.
✓ Branch 6 taken 15697 times.
✓ Branch 7 taken 365310 times.
381007 if (!m_use_shared_space && (!(THDVAR(m_thd, strict_mode)) || skip_strict())) {
14912 15697 return (nullptr);
14913 }
14914
14915 /* Check if a non-zero KEY_BLOCK_SIZE was specified. */
14916
2/2
✓ Branch 0 taken 299 times.
✓ Branch 1 taken 365011 times.
365310 if (has_key_block_size) {
14917
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 289 times.
299 if (is_temp) {
14918 10 my_error(ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE, MYF(0));
14919 10 return ("KEY_BLOCK_SIZE");
14920 }
14921
14922
2/2
✓ Branch 0 taken 280 times.
✓ Branch 1 taken 9 times.
289 switch (m_create_info->key_block_size) {
14923 ulint kbs_max;
14924 280 case 1:
14925 case 2:
14926 case 4:
14927 case 8:
14928 case 16:
14929 /* The maximum KEY_BLOCK_SIZE (KBS) is
14930 UNIV_PAGE_SIZE_MAX. But if UNIV_PAGE_SIZE is
14931 smaller than UNIV_PAGE_SIZE_MAX, the maximum
14932 KBS is also smaller. */
14933 560 kbs_max = std::min(1 << (UNIV_PAGE_SSIZE_MAX - 1),
14934 280 1 << (PAGE_ZIP_SSIZE_MAX - 1));
14935
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 280 times.
280 if (m_create_info->key_block_size > kbs_max) {
14936 push_warning_printf(
14937 m_thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION,
14938 "InnoDB: KEY_BLOCK_SIZE=%" PRIu32 " cannot be larger than %ld.",
14939 m_create_info->key_block_size, kbs_max);
14940 ret = "KEY_BLOCK_SIZE";
14941 }
14942
14943 /* The following checks do not appy to shared tablespaces */
14944
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 248 times.
280 if (m_use_shared_space) {
14945 32 break;
14946 }
14947
14948 /* Valid KEY_BLOCK_SIZE, check its dependencies. */
14949
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 241 times.
248 if (!m_allow_file_per_table) {
14950 7 push_warning(m_thd, Sql_condition::SL_WARNING,
14951 ER_ILLEGAL_HA_CREATE_OPTION,
14952 "InnoDB: KEY_BLOCK_SIZE requires"
14953 " innodb_file_per_table.");
14954 7 ret = "KEY_BLOCK_SIZE";
14955 }
14956 248 break;
14957 9 default:
14958 9 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
14959 ER_ILLEGAL_HA_CREATE_OPTION,
14960 "InnoDB: invalid KEY_BLOCK_SIZE = %" PRIu32
14961 ". Valid values are [1, 2, 4, 8, 16]",
14962 9 m_create_info->key_block_size);
14963 9 ret = "KEY_BLOCK_SIZE";
14964 9 break;
14965 }
14966 }
14967
14968 /* Check for a valid InnoDB ROW_FORMAT specifier and
14969 other incompatibilities. */
14970
5/5
✓ Branch 0 taken 768 times.
✓ Branch 1 taken 39594 times.
✓ Branch 2 taken 324931 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 1 times.
365300 switch (row_format) {
14971 768 case ROW_TYPE_COMPRESSED:
14972
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 763 times.
768 if (is_temp) {
14973 5 my_error(ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE, MYF(0));
14974 5 return ("ROW_FORMAT");
14975 }
14976
4/4
✓ Branch 0 taken 742 times.
✓ Branch 1 taken 21 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 740 times.
763 if (!m_use_shared_space && !m_allow_file_per_table) {
14977 2 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
14978 ER_ILLEGAL_HA_CREATE_OPTION,
14979 "InnoDB: %s requires innodb_file_per_table.",
14980 get_row_format_name(row_format));
14981 2 ret = "ROW_FORMAT";
14982 }
14983 763 break;
14984 39594 case ROW_TYPE_DYNAMIC:
14985 case ROW_TYPE_COMPACT:
14986 case ROW_TYPE_REDUNDANT:
14987
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 39572 times.
39594 if (has_key_block_size) {
14988 22 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
14989 ER_ILLEGAL_HA_CREATE_OPTION,
14990 "InnoDB: cannot specify %s"
14991 " with KEY_BLOCK_SIZE.",
14992 get_row_format_name(row_format));
14993 22 ret = "KEY_BLOCK_SIZE";
14994 }
14995 39594 break;
14996 324931 case ROW_TYPE_DEFAULT:
14997 324931 break;
14998 6 case ROW_TYPE_FIXED:
14999 case ROW_TYPE_PAGED:
15000 case ROW_TYPE_NOT_USED:
15001 6 push_warning(m_thd, Sql_condition::SL_WARNING,
15002 ER_ILLEGAL_HA_CREATE_OPTION,
15003 "InnoDB: invalid ROW_FORMAT specifier.");
15004 6 ret = "ROW_TYPE";
15005 6 break;
15006 }
15007
15008 754053 if (m_create_info->data_file_name != nullptr &&
15009
8/8
✓ Branch 0 taken 23463 times.
✓ Branch 1 taken 341832 times.
✓ Branch 2 taken 485 times.
✓ Branch 3 taken 22978 times.
✓ Branch 4 taken 410 times.
✓ Branch 5 taken 75 times.
✓ Branch 6 taken 25 times.
✓ Branch 7 taken 365270 times.
365705 *m_create_info->data_file_name != '\0' && m_table_name != nullptr &&
15010
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 385 times.
410 !create_option_data_directory_is_valid()) {
15011 25 ret = "DATA DIRECTORY";
15012 }
15013
15014 /* Do not allow INDEX_DIRECTORY */
15015
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 365291 times.
365295 if (m_create_info->index_file_name) {
15016 4 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
15017 ER_ILLEGAL_HA_CREATE_OPTION,
15018 "InnoDB: INDEX DIRECTORY is not supported");
15019 4 ret = "INDEX DIRECTORY";
15020 }
15021
15022 /* Don't support compressed table when page size > 16k. */
15023
4/4
✓ Branch 0 taken 365005 times.
✓ Branch 1 taken 290 times.
✓ Branch 2 taken 581 times.
✓ Branch 3 taken 364424 times.
365295 if ((has_key_block_size || row_format == ROW_TYPE_COMPRESSED) &&
15024
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 871 times.
871 UNIV_PAGE_SIZE > UNIV_PAGE_SIZE_DEF) {
15025 push_warning(m_thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION,
15026 "InnoDB: Cannot create a COMPRESSED table"
15027 " when innodb_page_size > 16k.");
15028
15029 if (has_key_block_size) {
15030 ret = "KEY_BLOCK_SIZE";
15031 } else {
15032 ret = "ROW_TYPE";
15033 }
15034 }
15035
15036 /* Validate the page compression parameter. */
15037
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 365270 times.
365295 if (!create_option_compression_is_valid()) {
15038 24 return ("COMPRESSION");
15039 }
15040
15041 /* Check the encryption option. */
15042
4/4
✓ Branch 0 taken 365202 times.
✓ Branch 1 taken 68 times.
✓ Branch 2 taken 54375 times.
✓ Branch 3 taken 310827 times.
365270 if (ret == nullptr && m_create_info->encrypt_type.str != nullptr) {
15043 dberr_t err;
15044
15045 54375 err = Encryption::validate(m_create_info->encrypt_type.str);
15046
15047
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54376 times.
54376 if (err == DB_UNSUPPORTED) {
15048 my_error(ER_INVALID_ENCRYPTION_OPTION, MYF(0));
15049 ret = "ENCRYPTION";
15050 }
15051 }
15052
15053 365271 return (ret);
15054 }
15055
15056 224965 void ha_innobase::adjust_encryption_key_id(HA_CREATE_INFO *create_info,
15057 dd::Properties *options) noexcept {
15058
2/2
✓ Branch 0 taken 224963 times.
✓ Branch 1 taken 2 times.
224965 if (false == create_info->was_encryption_key_id_set) {
15059
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 224963 times.
224963 if (Encryption::should_be_keyring_encrypted(
15060 224963 create_info->explicit_encryption, create_info->encrypt_type.str)) {
15061 create_info->encryption_key_id =
15062 THDVAR(current_thd, default_encryption_key_id);
15063 }
15064 } else {
15065
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (options && (create_info->tablespace == nullptr ||
15066 strcmp(create_info->tablespace,
15067 dict_sys_t::s_file_per_table_name) == 0)) {
15068 2 options->set("encryption_key_id", create_info->encryption_key_id);
15069 }
15070
15071
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
4 if (Encryption::is_master_key_encryption(create_info->encrypt_type.str) ||
15072 2 Encryption::none_explicitly_specified(create_info->explicit_encryption,
15073 2 create_info->encrypt_type.str)) {
15074 // if it is encrypted table with Master key encryption or marked as not to
15075 // be encrypted and alter table does not have ENCRYPTION_KEY_ID - mark
15076 // encryption key id as not set.
15077
15078 push_warning_printf(
15079 current_thd, Sql_condition::SL_WARNING, HA_WRONG_CREATE_OPTION,
15080 Encryption::none_explicitly_specified(
15081 create_info->explicit_encryption, create_info->encrypt_type.str)
15082 ? "InnoDB: Ignored ENCRYPTION_KEY_ID %u when "
15083 "encryption is disabled."
15084 : "InnoDB: Ignored ENCRYPTION_KEY_ID %u when "
15085 "Master Key encryption is enabled.",
15086 create_info->encryption_key_id);
15087 create_info->encryption_key_id = FIL_DEFAULT_ENCRYPTION_KEY;
15088 create_info->was_encryption_key_id_set = false;
15089 options->remove("encryption_key_id");
15090 }
15091 }
15092 224965 }
15093
15094 /** Adjust encryption options.
15095 @param[in,out] create_info Additional create information.
15096 @param[in,out] table_def dd::Table object to be modified.*/
15097 318377 void ha_innobase::adjust_encryption_options(HA_CREATE_INFO *create_info,
15098 dd::Table *table_def) noexcept {
15099 318377 bool is_intrinsic =
15100 318377 (create_info->options & HA_LEX_CREATE_INTERNAL_TMP_TABLE) != 0;
15101
15102
2/2
✓ Branch 0 taken 110977 times.
✓ Branch 1 taken 207400 times.
318377 if (is_intrinsic) {
15103 110977 return;
15104 }
15105
15106 #ifdef UNIV_DEBUG
15107 // check that create_info->explicit_encryption is in sync with
15108 // DD's explicit_encryption
15109
2/2
✓ Branch 0 taken 13527 times.
✓ Branch 1 taken 193873 times.
207400 if (create_info->explicit_encryption) {
15110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13527 times.
13527 ut_ad(table_def->options().exists("explicit_encryption"));
15111 13527 bool explicit_encryption{false};
15112 13527 table_def->options().get("explicit_encryption", &explicit_encryption);
15113
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13527 times.
13527 ut_ad(explicit_encryption);
15114 }
15115 #endif /* UNIV_DEBUG */
15116
15117 207400 bool is_tmp = (create_info->options & HA_LEX_CREATE_TMP_TABLE) != 0;
15118
15119
2/2
✓ Branch 0 taken 42539 times.
✓ Branch 1 taken 164861 times.
207400 if (is_tmp) {
15120 42539 return;
15121 }
15122
15123
1/2
✓ Branch 0 taken 164861 times.
✗ Branch 1 not taken.
329722 adjust_encryption_key_id(create_info,
15124 164861 table_def ? &(table_def->options()) : nullptr);
15125 }
15126
15127 /** Update create_info. Used in SHOW CREATE TABLE et al. */
15128
15129 124154 void ha_innobase::update_create_info(
15130 HA_CREATE_INFO *create_info) /*!< in/out: create info */
15131 {
15132
2/2
✓ Branch 0 taken 123961 times.
✓ Branch 1 taken 193 times.
124154 if (!(create_info->used_fields & HA_CREATE_USED_AUTO)) {
15133 123961 info(HA_STATUS_AUTO);
15134 123961 create_info->auto_increment_value = stats.auto_increment_value;
15135 }
15136
15137 /* Update the DATA DIRECTORY name. */
15138 124154 dd_get_and_save_data_dir_path<dd::Table>(m_prebuilt->table, nullptr, false);
15139
15140
2/2
✓ Branch 0 taken 172 times.
✓ Branch 1 taken 123982 times.
124154 if (m_prebuilt->table->data_dir_path != nullptr) {
15141 172 create_info->data_file_name = m_prebuilt->table->data_dir_path;
15142 }
15143
15144 /* Update the TABLESPACE name from the Data Dictionary. */
15145 124154 dict_get_and_save_space_name(m_prebuilt->table);
15146
15147 /* Put this tablespace name into the create_info structure so that
15148 SHOW CREATE TABLE will display TABLESPACE=name. This also affects
15149 an ALTER TABLE which must know the current TABLESPACE so that the
15150 table will stay there. */
15151
4/4
✓ Branch 0 taken 38046 times.
✓ Branch 1 taken 86108 times.
✓ Branch 2 taken 2244 times.
✓ Branch 3 taken 121910 times.
162200 if (m_prebuilt->table->tablespace != nullptr &&
15152
2/2
✓ Branch 0 taken 2244 times.
✓ Branch 1 taken 35802 times.
38046 create_info->tablespace == nullptr) {
15153 2244 create_info->tablespace = m_prebuilt->table->tablespace;
15154 }
15155 124154 }
15156
15157 /** Initialize the table FTS stopword list
15158 @return true if success */
15159 649 bool innobase_fts_load_stopword(
15160 dict_table_t *table, /*!< in: Table has the FTS */
15161 trx_t *trx, /*!< in: transaction */
15162 THD *thd) /*!< in: current thread */
15163 {
15164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 649 times.
649 ut_ad(!dict_sys_mutex_own());
15165
15166 1947 return (fts_load_stopword(table, trx, innobase_server_stopword_table,
15167 649 THDVAR(thd, ft_user_stopword_table),
15168 1298 THDVAR(thd, ft_enable_stopword), false));
15169 }
15170
15171 9707 static bool innobase_ddse_dict_init(
15172 dict_init_mode_t dict_init_mode, uint, List<const dd::Object_table> *tables,
15173 List<const Plugin_tablespace> *tablespaces) {
15174
1/2
✓ Branch 0 taken 9707 times.
✗ Branch 1 not taken.
9707 DBUG_TRACE;
15175
15176
8/16
✓ Branch 0 taken 9707 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9707 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9707 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9707 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 9707 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 9707 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 9707 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 9707 times.
✗ Branch 15 not taken.
9707 LogErr(SYSTEM_LEVEL, ER_IB_MSG_INNODB_START_INITIALIZE);
15177
15178
2/4
✓ Branch 0 taken 9707 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9707 times.
✗ Branch 3 not taken.
9707 assert(tables && tables->is_empty());
15179
2/4
✓ Branch 0 taken 9707 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9707 times.
✗ Branch 3 not taken.
9707 assert(tablespaces && tablespaces->is_empty());
15180
15181
2/2
✓ Branch 0 taken 9631 times.
✓ Branch 1 taken 76 times.
9707 if (dblwr::is_enabled()) {
15182
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 9623 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
9631 if (innobase_doublewrite_dir != nullptr && *innobase_doublewrite_dir != 0) {
15183
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 dblwr::dir.assign(innobase_doublewrite_dir);
15184
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 switch (dblwr::dir.front()) {
15185 case '#':
15186 case '.':
15187 break;
15188 8 default:
15189
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
8 if (!Fil_path::is_absolute_path(dblwr::dir)) {
15190 dblwr::dir.insert(0, "#");
15191 }
15192 }
15193
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
16 ib::info(ER_IB_MSG_DBLWR_1325)
15194
3/6
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
16 << "Using " << dblwr::dir << " as doublewrite directory";
15195 } else {
15196
1/2
✓ Branch 0 taken 9623 times.
✗ Branch 1 not taken.
9623 dblwr::dir.assign(".");
15197 }
15198
2/4
✓ Branch 0 taken 9631 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9631 times.
✗ Branch 3 not taken.
9631 ib::info(ER_IB_MSG_DBLWR_1304) << "Atomic write enabled";
15199 } else {
15200
2/4
✓ Branch 0 taken 76 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 76 times.
✗ Branch 3 not taken.
76 ib::info(ER_IB_MSG_DBLWR_1305) << "Atomic write disabled";
15201 }
15202
15203 9707 bool is_dd_encrypted{false};
15204
15205
3/4
✓ Branch 0 taken 9706 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 84 times.
✓ Branch 3 taken 9622 times.
9707 if (innobase_init_files(dict_init_mode, tablespaces, is_dd_encrypted)) {
15206 84 return true;
15207 }
15208
15209 /* Instantiate table defs only if we are successful so far. */
15210 dd::Object_table *innodb_dynamic_metadata =
15211
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 dd::Object_table::create_object_table();
15212
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 innodb_dynamic_metadata->set_hidden(true);
15213 dd::Object_table_definition *def =
15214
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 innodb_dynamic_metadata->target_table_definition();
15215
2/4
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
9622 def->set_table_name("innodb_dynamic_metadata");
15216
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_field(0, "table_id", "table_id BIGINT UNSIGNED NOT NULL");
15217
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_field(1, "version", "version BIGINT UNSIGNED NOT NULL");
15218
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_field(2, "metadata", "metadata BLOB NOT NULL");
15219
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_index(0, "index_pk", "PRIMARY KEY (table_id)");
15220 /* Options and tablespace are set at the SQL layer. */
15221
15222 /* Changing these values would change the specification of innodb statistics
15223 tables. */
15224 static constexpr size_t DB_NAME_FIELD_SIZE = 64;
15225 static constexpr size_t TABLE_NAME_FIELD_SIZE = 199;
15226
15227 static_assert(DB_NAME_FIELD_SIZE == dict_name::MAX_DB_CHAR_LEN,
15228 "dict_name::MAX_DB_CHAR_LEN mismatch with db column");
15229
15230 static_assert(TABLE_NAME_FIELD_SIZE == dict_name::MAX_TABLE_CHAR_LEN,
15231 "dict_name::MAX_TABLE_CHAR_LEN mismatch with table column");
15232
15233 /* Set length for database name field. */
15234
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
19244 std::ostringstream db_name_field;
15235
2/4
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
9622 db_name_field << "database_name VARCHAR(" << DB_NAME_FIELD_SIZE
15236
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 << ") NOT NULL";
15237
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
19244 std::string db_field = db_name_field.str();
15238
15239 /* Set length for table name field. */
15240
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
19244 std::ostringstream table_name_field;
15241
2/4
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
9622 table_name_field << "table_name VARCHAR(" << TABLE_NAME_FIELD_SIZE
15242
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 << ") NOT NULL";
15243
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 std::string table_field = table_name_field.str();
15244
15245 dd::Object_table *innodb_table_stats =
15246
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 dd::Object_table::create_object_table();
15247
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 innodb_table_stats->set_hidden(false);
15248
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 def = innodb_table_stats->target_table_definition();
15249
2/4
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
9622 def->set_table_name("innodb_table_stats");
15250
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_field(0, "database_name", db_field.c_str());
15251
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_field(1, "table_name", table_field.c_str());
15252
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_field(2, "last_update",
15253 "last_update TIMESTAMP NOT NULL \n"
15254 " DEFAULT CURRENT_TIMESTAMP \n"
15255 " ON UPDATE CURRENT_TIMESTAMP");
15256
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_field(3, "n_rows", "n_rows BIGINT UNSIGNED NOT NULL");
15257
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_field(4, "clustered_index_size",
15258 "clustered_index_size BIGINT UNSIGNED NOT NULL");
15259
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_field(5, "sum_of_other_index_sizes",
15260 "sum_of_other_index_sizes BIGINT UNSIGNED NOT NULL");
15261
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_index(0, "index_pk", "PRIMARY KEY (database_name, table_name)");
15262 /* Options and tablespace are set at the SQL layer. */
15263
15264 dd::Object_table *innodb_index_stats =
15265
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 dd::Object_table::create_object_table();
15266
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 innodb_index_stats->set_hidden(false);
15267
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 def = innodb_index_stats->target_table_definition();
15268
2/4
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
9622 def->set_table_name("innodb_index_stats");
15269
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_field(0, "database_name", db_field.c_str());
15270
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_field(1, "table_name", table_field.c_str());
15271
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_field(2, "index_name", "index_name VARCHAR(64) NOT NULL");
15272
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_field(3, "last_update",
15273 "last_update TIMESTAMP NOT NULL"
15274 " DEFAULT CURRENT_TIMESTAMP"
15275 " ON UPDATE CURRENT_TIMESTAMP");
15276 /*
15277 There are at least: stat_name='size'
15278 stat_name='n_leaf_pages'
15279 stat_name='n_diff_pfx%'
15280 */
15281
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_field(4, "stat_name", "stat_name VARCHAR(64) NOT NULL");
15282
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_field(5, "stat_value", "stat_value BIGINT UNSIGNED NOT NULL");
15283
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_field(6, "sample_size", "sample_size BIGINT UNSIGNED");
15284
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_field(7, "stat_description",
15285 "stat_description VARCHAR(1024) NOT NULL");
15286
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_index(0, "index_pk",
15287 "PRIMARY KEY (database_name, table_name, "
15288 "index_name, stat_name)");
15289 /* Options and tablespace are set at the SQL layer. */
15290
15291
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 dd::Object_table *innodb_ddl_log = dd::Object_table::create_object_table();
15292
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 innodb_ddl_log->set_hidden(true);
15293
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 def = innodb_ddl_log->target_table_definition();
15294
2/4
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
9622 def->set_table_name("innodb_ddl_log");
15295
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_field(0, "id", "id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT");
15296
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_field(1, "thread_id", "thread_id BIGINT UNSIGNED NOT NULL");
15297
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_field(2, "type", "type INT UNSIGNED NOT NULL");
15298
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_field(3, "space_id", "space_id INT UNSIGNED");
15299
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_field(4, "page_no", "page_no INT UNSIGNED");
15300
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_field(5, "index_id", "index_id BIGINT UNSIGNED");
15301
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_field(6, "table_id", "table_id BIGINT UNSIGNED");
15302
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_field(7, "old_file_path",
15303 "old_file_path VARCHAR(512) COLLATE UTF8_BIN");
15304
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_field(8, "new_file_path",
15305 "new_file_path VARCHAR(512) COLLATE UTF8_BIN");
15306
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_index(0, "index_pk", "PRIMARY KEY(id)");
15307
3/6
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
9622 def->add_index(1, "index_k_thread_id", "KEY(thread_id)");
15308 /* Options and tablespace are set at the SQL layer. */
15309
15310
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 9602 times.
9622 if (is_dd_encrypted) {
15311
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 innodb_dynamic_metadata->set_target_encrypted();
15312
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 innodb_table_stats->set_target_encrypted();
15313
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 innodb_index_stats->set_target_encrypted();
15314
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 innodb_ddl_log->set_target_encrypted();
15315 }
15316
15317
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 tables->push_back(innodb_dynamic_metadata);
15318
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 tables->push_back(innodb_table_stats);
15319
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 tables->push_back(innodb_index_stats);
15320
1/2
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
9622 tables->push_back(innodb_ddl_log);
15321
15322
8/16
✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9622 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 9622 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 9622 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 9622 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 9622 times.
✗ Branch 15 not taken.
9622 LogErr(SYSTEM_LEVEL, ER_IB_MSG_INNODB_END_INITIALIZE);
15323
15324 9622 return false;
15325 9706 }
15326
15327 /** Initialize the set of hard coded DD table ids.
15328 @param[in] dd_table_id Table id of DD table. */
15329 328487 static void innobase_dict_register_dd_table_id(dd::Object_id dd_table_id) {
15330 328487 dict_sys_t::s_dd_table_ids.insert(dd_table_id);
15331 328487 }
15332
15333 /** Parse the table name into normal name and remote path if needed.
15334 @param[in] name Table name (db/table or full path).
15335 @return 0 if successful, otherwise, error number */
15336 352242 int create_table_info_t::parse_table_name(const char *name) {
15337
1/2
✓ Branch 0 taken 352242 times.
✗ Branch 1 not taken.
352242 DBUG_TRACE;
15338
15339 #ifdef _WIN32
15340 /* Names passed in from server are in two formats:
15341 1. <database_name>/<table_name>: for normal table creation
15342 2. full path: for temp table creation, or DATA DIRECTORY.
15343
15344 When srv_file_per_table is on,
15345 check for full path pattern, i.e.
15346 X:\dir\..., X is a driver letter, or
15347 \\dir1\dir2\..., UNC path
15348 returns error if it is in full path format, but not creating a temp.
15349 table. Currently InnoDB does not support symbolic link on Windows. */
15350
15351 if (m_innodb_file_per_table &&
15352 !(m_create_info->options & HA_LEX_CREATE_TMP_TABLE)) {
15353 if (name[1] == ':' || (name[0] == '\\' && name[1] == '\\')) {
15354 log_errlog(ERROR_LEVEL, ER_INNODB_CANNOT_CREATE_TABLE, name);
15355 return HA_ERR_GENERIC;
15356 }
15357 }
15358 #endif /* _WIN32 */
15359
15360
2/4
✓ Branch 0 taken 352241 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 352241 times.
352242 if (!normalize_table_name(m_table_name, name)) {
15361 /* purecov: begin inspected */
15362 ut_d(ut_error);
15363 ut_o(return (HA_ERR_TOO_LONG_PATH));
15364 /* purecov: end */
15365 }
15366
15367 352241 m_remote_path[0] = '\0';
15368 352241 m_tablespace[0] = '\0';
15369
15370 /* Set the remote path if DATA DIRECTORY is valid. If not,
15371 we ignore the DATA DIRECTORY. In strict mode, a non-valid
15372 value would have already been rejected. */
15373
2/2
✓ Branch 0 taken 23582 times.
✓ Branch 1 taken 328659 times.
352241 if (m_create_info->data_file_name != nullptr &&
15374
3/4
✓ Branch 0 taken 468 times.
✓ Branch 1 taken 23114 times.
✓ Branch 2 taken 468 times.
✗ Branch 3 not taken.
23582 *m_create_info->data_file_name != '\0' && m_table_name != nullptr) {
15375
3/4
✓ Branch 0 taken 468 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 455 times.
468 if (!create_option_data_directory_is_valid(true)) {
15376
2/4
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
13 push_warning_printf(m_thd, Sql_condition::SL_WARNING, WARN_OPTION_IGNORED,
15377 ER_DEFAULT(WARN_OPTION_IGNORED), "DATA DIRECTORY");
15378 13 m_flags &= ~DICT_TF_MASK_DATA_DIR;
15379 } else {
15380 455 strncpy(m_remote_path, m_create_info->data_file_name, FN_REFLEN - 1);
15381 }
15382 }
15383
15384
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 352203 times.
352241 if (m_create_info->index_file_name) {
15385
2/4
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
✗ Branch 3 not taken.
38 push_warning_printf(m_thd, Sql_condition::SL_WARNING, WARN_OPTION_IGNORED,
15386 ER_DEFAULT(WARN_OPTION_IGNORED), "INDEX DIRECTORY");
15387 }
15388
15389 /* The TABLESPACE designation has already been validated by
15390 create_option_tablespace_is_valid() irregardless of strict-mode.
15391 So it only needs to be copied now. */
15392
2/2
✓ Branch 0 taken 24392 times.
✓ Branch 1 taken 327849 times.
352241 if (m_use_shared_space) {
15393 24392 strncpy(m_tablespace, m_create_info->tablespace, NAME_LEN - 1);
15394 }
15395
15396 352240 return 0;
15397 352241 }
15398
15399 /** Determine InnoDB table flags.
15400 If strict_mode=OFF, this will adjust the flags to what should be assumed.
15401 However, if an existing general tablespace is being targeted, we will NOT
15402 assume anything or adjust these flags.
15403 @retval true if successful, false if error */
15404 395991 bool create_table_info_t::innobase_table_flags() {
15405
1/2
✓ Branch 0 taken 395992 times.
✗ Branch 1 not taken.
395991 DBUG_TRACE;
15406
15407 395992 const char *fts_doc_id_index_bad = nullptr;
15408 395992 uint32_t zip_ssize = 0;
15409 395992 const bool is_temp = m_create_info->options & HA_LEX_CREATE_TMP_TABLE;
15410 395992 bool zip_allowed = !is_temp;
15411
15412 const uint32_t zip_ssize_max =
15413 395992 std::min<uint32_t>((UNIV_PAGE_SSIZE_MAX), (PAGE_ZIP_SSIZE_MAX));
15414
15415 395992 m_flags = 0;
15416 395992 m_flags2 = 0;
15417
15418 /* Validate the page compression parameter. */
15419
1/2
✓ Branch 0 taken 395992 times.
✗ Branch 1 not taken.
395992 if (!create_option_compression_is_valid()) {
15420 /* No need to do anything. Warnings were issued.
15421 The compresion setting will be ignored later.
15422 If inodb_strict_mode=ON, this is called twice unless
15423 there was a problem before.
15424 If inodb_strict_mode=OFF, this is the only call. */
15425 }
15426
15427 /* Validate the page encryption parameter. */
15428
2/2
✓ Branch 0 taken 84366 times.
✓ Branch 1 taken 311626 times.
395992 if (m_create_info->encrypt_type.length > 0) {
15429 84366 const char *encryption = m_create_info->encrypt_type.str;
15430
15431
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84366 times.
84366 if (Encryption::validate(encryption) != DB_SUCCESS) {
15432 /* Incorrect encryption option */
15433 my_error(ER_INVALID_ENCRYPTION_OPTION, MYF(0));
15434 return false;
15435 }
15436 }
15437
15438 /* Check if there are any FTS indexes defined on this table. */
15439
2/2
✓ Branch 0 taken 227023 times.
✓ Branch 1 taken 395989 times.
623012 for (uint i = 0; i < m_form->s->keys; i++) {
15440 227023 const KEY *key = &m_form->key_info[i];
15441
15442
2/2
✓ Branch 0 taken 2027 times.
✓ Branch 1 taken 224996 times.
227023 if (key->flags & HA_FULLTEXT) {
15443 2027 m_flags2 |= DICT_TF2_FTS;
15444
15445 /* We don't support FTS indexes in temporary
15446 tables. */
15447
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2026 times.
2027 if (is_temp) {
15448
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_INNODB_NO_FT_TEMP_TABLE, MYF(0));
15449 1 return false;
15450 }
15451
15452
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2024 times.
2026 if (fts_doc_id_index_bad) {
15453 2 goto index_bad;
15454 }
15455
2/2
✓ Branch 0 taken 583 times.
✓ Branch 1 taken 224413 times.
224996 } else if (key->flags & HA_SPATIAL) {
15456
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 583 times.
583 assert(~m_create_info->options &
15457 (HA_LEX_CREATE_TMP_TABLE | HA_LEX_CREATE_INTERNAL_TMP_TABLE));
15458 }
15459
15460
3/4
✓ Branch 0 taken 227020 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 226972 times.
✓ Branch 3 taken 48 times.
227020 if (innobase_strcasecmp(key->name, FTS_DOC_ID_INDEX_NAME)) {
15461 226972 continue;
15462 }
15463
15464 /* Do a pre-check on FTS DOC ID index */
15465
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 if (!(key->flags & HA_NOSAME)
15466 /* For now, we do not allow a descending index,
15467 because fts_doc_fetch_by_doc_id() uses the
15468 InnODB SQL interpreter to look up FTS_DOC_ID.*/
15469
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 5 times.
48 || (key->key_part[0].key_part_flag & HA_REVERSE_SORT) ||
15470
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 strcmp(key->name, FTS_DOC_ID_INDEX_NAME) ||
15471
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 41 times.
43 strcmp(key->key_part[0].field->field_name, FTS_DOC_ID_COL_NAME)) {
15472 7 fts_doc_id_index_bad = key->name;
15473 }
15474
15475
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 41 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
48 if (fts_doc_id_index_bad && (m_flags2 & DICT_TF2_FTS)) {
15476 index_bad:
15477
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_INNODB_FT_WRONG_DOCID_INDEX, MYF(0), fts_doc_id_index_bad);
15478 2 return false;
15479 }
15480 }
15481
15482
4/4
✓ Branch 0 taken 153491 times.
✓ Branch 1 taken 242498 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 153475 times.
395989 if (is_temp && m_create_info->key_block_size > 0) {
15483
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 push_warning(m_thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION,
15484 "InnoDB: KEY_BLOCK_SIZE is ignored"
15485 " for TEMPORARY TABLE.");
15486 16 zip_allowed = false;
15487
2/2
✓ Branch 0 taken 409 times.
✓ Branch 1 taken 395564 times.
395973 } else if (m_create_info->key_block_size > 0) {
15488
1/2
✓ Branch 0 taken 409 times.
✗ Branch 1 not taken.
409 zip_ssize = get_zip_shift_size(m_create_info->key_block_size);
15489
15490 /* Make sure compressed row format is allowed. */
15491
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 409 times.
409 if (is_temp) {
15492 push_warning(m_thd, Sql_condition::SL_WARNING,
15493 ER_ILLEGAL_HA_CREATE_OPTION,
15494 "InnoDB: KEY_BLOCK_SIZE is ignored"
15495 " for TEMPORARY TABLE.");
15496 zip_allowed = false;
15497
3/4
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 394 times.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
409 } else if (!m_allow_file_per_table && !m_use_shared_space) {
15498
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 push_warning(m_thd, Sql_condition::SL_WARNING,
15499 ER_ILLEGAL_HA_CREATE_OPTION,
15500 "InnoDB: KEY_BLOCK_SIZE requires"
15501 " innodb_file_per_table.");
15502 15 zip_allowed = false;
15503 }
15504
15505
5/6
✓ Branch 0 taken 394 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 392 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
409 if (!zip_allowed || (!zip_ssize && m_create_info->key_block_size)) {
15506 17 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
15507 ER_ILLEGAL_HA_CREATE_OPTION,
15508 "InnoDB: ignoring KEY_BLOCK_SIZE=%" PRIu32 ".",
15509
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 m_create_info->key_block_size);
15510 }
15511 }
15512
15513 395989 enum row_type row_type = m_form->s->row_type;
15514
15515
4/4
✓ Branch 0 taken 406 times.
✓ Branch 1 taken 395583 times.
✓ Branch 2 taken 392 times.
✓ Branch 3 taken 14 times.
395989 if (zip_ssize && zip_allowed) {
15516 /* if ROW_FORMAT is set to default,
15517 automatically change it to COMPRESSED. */
15518
2/2
✓ Branch 0 taken 115 times.
✓ Branch 1 taken 277 times.
392 if (row_type == ROW_TYPE_DEFAULT) {
15519 115 row_type = ROW_TYPE_COMPRESSED;
15520
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 261 times.
277 } else if (row_type != ROW_TYPE_COMPRESSED) {
15521 /* ROW_FORMAT other than COMPRESSED
15522 ignores KEY_BLOCK_SIZE. It does not
15523 make sense to reject conflicting
15524 KEY_BLOCK_SIZE and ROW_FORMAT, because
15525 such combinations can be obtained
15526 with ALTER TABLE anyway. */
15527 16 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
15528 ER_ILLEGAL_HA_CREATE_OPTION,
15529 "InnoDB: ignoring KEY_BLOCK_SIZE=%" PRIu32
15530 " as ROW_FORMAT is not COMPRESSED.",
15531
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 m_create_info->key_block_size);
15532 16 zip_allowed = false;
15533 }
15534 } else {
15535 /* zip_ssize == 0 means no KEY_BLOCK_SIZE. */
15536
4/4
✓ Branch 0 taken 665 times.
✓ Branch 1 taken 394932 times.
✓ Branch 2 taken 643 times.
✓ Branch 3 taken 22 times.
395597 if (row_type == ROW_TYPE_COMPRESSED && zip_allowed) {
15537 /* ROW_FORMAT=COMPRESSED without KEY_BLOCK_SIZE
15538 implies half the maximum KEY_BLOCK_SIZE(*1k) or
15539 UNIV_PAGE_SIZE, whichever is less. */
15540 643 zip_ssize = zip_ssize_max - 1;
15541 }
15542 }
15543
15544
1/2
✓ Branch 0 taken 395987 times.
✗ Branch 1 not taken.
395989 rec_format_t innodb_row_format = get_row_format(innodb_default_row_format);
15545
6/7
✓ Branch 0 taken 1230 times.
✓ Branch 1 taken 1374 times.
✓ Branch 2 taken 1041 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 36919 times.
✓ Branch 5 taken 355418 times.
✗ Branch 6 not taken.
395987 switch (row_type) {
15546 1230 case ROW_TYPE_REDUNDANT:
15547 1230 innodb_row_format = REC_FORMAT_REDUNDANT;
15548 1230 break;
15549 1374 case ROW_TYPE_COMPACT:
15550 1374 innodb_row_format = REC_FORMAT_COMPACT;
15551 1374 break;
15552
15553 1041 case ROW_TYPE_COMPRESSED:
15554
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1026 times.
1041 if (is_temp) {
15555
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
15556 ER_ILLEGAL_HA_CREATE_OPTION,
15557 "InnoDB: %s is ignored for TEMPORARY TABLE.",
15558 get_row_format_name(row_type));
15559
15560 /* DYNAMIC row format is closer to COMPRESSED
15561 in that it supports better for large BLOBs. */
15562
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 push_warning(m_thd, Sql_condition::SL_WARNING,
15563 ER_ILLEGAL_HA_CREATE_OPTION,
15564 "InnoDB: assuming ROW_FORMAT=DYNAMIC.");
15565
15566 15 row_type = ROW_TYPE_DYNAMIC;
15567 15 innodb_row_format = REC_FORMAT_DYNAMIC;
15568 15 break;
15569 }
15570
15571 /* ROW_FORMAT=COMPRESSED requires file_per_table unless
15572 there is a target tablespace. */
15573
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1018 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
1026 if (!m_allow_file_per_table && !m_use_shared_space) {
15574
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
15575 ER_ILLEGAL_HA_CREATE_OPTION,
15576 "InnoDB: %s requires innodb_file_per_table.",
15577 get_row_format_name(row_type));
15578 } else {
15579 /* We can use this row_format. */
15580 1018 innodb_row_format = REC_FORMAT_COMPRESSED;
15581 1018 break;
15582 }
15583 8 zip_allowed = false;
15584 /* fall through to set row_type = DYNAMIC */
15585 [[fallthrough]];
15586 13 case ROW_TYPE_NOT_USED:
15587 case ROW_TYPE_FIXED:
15588 case ROW_TYPE_PAGED:
15589
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 push_warning(m_thd, Sql_condition::SL_WARNING,
15590 ER_ILLEGAL_HA_CREATE_OPTION,
15591 "InnoDB: assuming ROW_FORMAT=DYNAMIC.");
15592 [[fallthrough]];
15593 36932 case ROW_TYPE_DYNAMIC:
15594 36932 innodb_row_format = REC_FORMAT_DYNAMIC;
15595 36932 break;
15596 355418 case ROW_TYPE_DEFAULT: {
15597 /* Consider the real_row_type if already set. */
15598
4/5
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 153 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 355159 times.
✓ Branch 4 taken 79 times.
355418 switch (m_form->s->real_row_type) {
15599 27 case ROW_TYPE_REDUNDANT:
15600 27 innodb_row_format = REC_FORMAT_REDUNDANT;
15601 27 break;
15602 153 case ROW_TYPE_COMPACT:
15603 153 innodb_row_format = REC_FORMAT_COMPACT;
15604 153 break;
15605 case ROW_TYPE_COMPRESSED:
15606 innodb_row_format = REC_FORMAT_COMPRESSED;
15607 break;
15608 355159 case ROW_TYPE_DYNAMIC:
15609 355159 innodb_row_format = REC_FORMAT_DYNAMIC;
15610 355159 break;
15611 79 default:
15612 79 break;
15613 }
15614 355418 break;
15615 }
15616 default:
15617 ut_d(ut_error);
15618 }
15619
15620 /* Don't support compressed table when page size > 16k. */
15621
5/6
✓ Branch 0 taken 242466 times.
✓ Branch 1 taken 153521 times.
✓ Branch 2 taken 1018 times.
✓ Branch 3 taken 241448 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1018 times.
395987 if (zip_allowed && zip_ssize && UNIV_PAGE_SIZE > UNIV_PAGE_SIZE_DEF) {
15622 push_warning(m_thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION,
15623 "InnoDB: Cannot create a COMPRESSED table"
15624 " when innodb_page_size > 16k."
15625 " Assuming ROW_FORMAT=DYNAMIC.");
15626 zip_allowed = false;
15627 }
15628
15629
4/6
✓ Branch 0 taken 153490 times.
✓ Branch 1 taken 242497 times.
✓ Branch 2 taken 153490 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 395989 times.
395987 ut_ad(!is_temp || !zip_allowed);
15630
4/6
✓ Branch 0 taken 153491 times.
✓ Branch 1 taken 242498 times.
✓ Branch 2 taken 153491 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 395988 times.
395989 ut_ad(!is_temp || row_type != ROW_TYPE_COMPRESSED);
15631
5/6
✓ Branch 0 taken 153490 times.
✓ Branch 1 taken 242498 times.
✓ Branch 2 taken 153490 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 395987 times.
395988 ut_ad(!is_temp || innodb_row_format != REC_FORMAT_COMPRESSED);
15632
15633 /* Set the table flags */
15634
2/2
✓ Branch 0 taken 153523 times.
✓ Branch 1 taken 242464 times.
395987 if (!zip_allowed) {
15635 153523 zip_ssize = 0;
15636 }
15637
15638
2/2
✓ Branch 0 taken 153490 times.
✓ Branch 1 taken 242497 times.
395987 if (is_temp) {
15639 153490 m_flags2 |= DICT_TF2_TEMPORARY;
15640
15641
2/2
✓ Branch 0 taken 110977 times.
✓ Branch 1 taken 42513 times.
153490 if (m_create_info->options & HA_LEX_CREATE_INTERNAL_TMP_TABLE) {
15642 /* Intrinsic tables reside only in the shared temporary
15643 tablespace and we will always use ROW_FORMAT=DYNAMIC. */
15644 /* We do not allow compressed instrinsic temporary tables. */
15645
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 110977 times.
110977 ut_ad(zip_ssize == 0);
15646 110977 innodb_row_format = REC_FORMAT_DYNAMIC;
15647 110977 m_flags2 |= DICT_TF2_INTRINSIC;
15648 }
15649
3/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 153481 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
153490 if (m_use_shared_space && m_create_info->tablespace != nullptr &&
15650
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 strcmp(m_create_info->tablespace, dict_sys_t::s_temp_space_name) == 0) {
15651 /* This is possible only with innodb_strict_mode=OFF and we warned that
15652 that tablespace=innodb_temporary is ignored. We should instead use
15653 session temporary tablespaces */
15654 9 m_use_shared_space = false;
15655 }
15656
15657
2/2
✓ Branch 0 taken 195884 times.
✓ Branch 1 taken 46613 times.
242497 } else if (m_use_file_per_table) {
15658
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195885 times.
195884 ut_ad(!m_use_shared_space);
15659 195885 m_flags2 |= DICT_TF2_USE_FILE_PER_TABLE;
15660 }
15661
15662 /* Set the table flags */
15663 395988 dict_tf_set(&m_flags, innodb_row_format, zip_ssize, m_use_data_dir,
15664
1/2
✓ Branch 0 taken 395989 times.
✗ Branch 1 not taken.
395988 m_use_shared_space);
15665
15666 395989 return true;
15667 395992 }
15668
15669 /** Detach the just created table and its auxiliary tables if exist */
15670 176425 void create_table_info_t::detach() {
15671
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 176425 times.
176425 ut_ad(!dict_sys_mutex_own());
15672 176425 dict_sys_mutex_enter();
15673
15674
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 176425 times.
176425 ut_ad(m_table != nullptr);
15675
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 176425 times.
176425 ut_ad(!m_table->can_be_evicted);
15676
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 176425 times.
176425 ut_ad(!m_table->is_temporary());
15677
15678
2/2
✓ Branch 0 taken 166563 times.
✓ Branch 1 taken 9862 times.
176425 if (!m_table->explicitly_non_lru) {
15679 166563 dict_table_allow_eviction(m_table);
15680 }
15681
15682
2/2
✓ Branch 0 taken 176005 times.
✓ Branch 1 taken 420 times.
176425 if ((m_table->flags2 & (DICT_TF2_FTS | DICT_TF2_FTS_ADD_DOC_ID)) ||
15683
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 176005 times.
176005 m_table->fts != nullptr) {
15684 420 fts_detach_aux_tables(m_table, true);
15685 }
15686
15687 176425 dict_sys_mutex_exit();
15688 176425 }
15689
15690 /** Parse MERGE_THRESHOLD value from the string.
15691 @param[in] thd connection
15692 @param[in] str string which might include 'MERGE_THRESHOLD='
15693 @return value parsed. 0 means not found or invalid value. */
15694 33676 static ulint innobase_parse_merge_threshold(THD *thd, const char *str) {
15695 static const char *label = "MERGE_THRESHOLD=";
15696
3/4
✓ Branch 0 taken 470 times.
✓ Branch 1 taken 33206 times.
✓ Branch 2 taken 470 times.
✗ Branch 3 not taken.
33676 static const size_t label_len = strlen(label);
15697 33676 const char *pos = str;
15698
15699 33676 pos = strstr(str, label);
15700
15701
2/2
✓ Branch 0 taken 33601 times.
✓ Branch 1 taken 75 times.
33676 if (pos == nullptr) {
15702 33601 return (0);
15703 }
15704
15705 75 pos += label_len;
15706
15707 75 lint ret = atoi(pos);
15708
15709
4/4
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 56 times.
✓ Branch 3 taken 10 times.
75 if (ret > 0 && ret <= 50) {
15710 56 return (static_cast<ulint>(ret));
15711 }
15712
15713 19 push_warning_printf(
15714 thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION,
15715 "InnoDB: Invalid value for MERGE_THRESHOLD in the CREATE TABLE"
15716 " statement. The value is ignored.");
15717
15718 19 return (0);
15719 }
15720
15721 /** Parse hint for table and its indexes, and update the information
15722 in dictionary.
15723 @param[in] thd Connection thread
15724 @param[in,out] table Target table
15725 @param[in] table_share Table definition */
15726 401063 void innobase_parse_hint_from_comment(THD *thd, dict_table_t *table,
15727 const TABLE_SHARE *table_share) {
15728 ulint merge_threshold_table;
15729 ulint merge_threshold_index[MAX_KEY];
15730 bool is_found[MAX_KEY];
15731
15732
2/2
✓ Branch 0 taken 33440 times.
✓ Branch 1 taken 367623 times.
401063 if (table_share->comment.str != nullptr) {
15733 merge_threshold_table =
15734
1/2
✓ Branch 0 taken 33440 times.
✗ Branch 1 not taken.
33440 innobase_parse_merge_threshold(thd, table_share->comment.str);
15735 } else {
15736 367623 merge_threshold_table = DICT_INDEX_MERGE_THRESHOLD_DEFAULT;
15737 }
15738
15739
2/2
✓ Branch 0 taken 33430 times.
✓ Branch 1 taken 367633 times.
401063 if (merge_threshold_table == 0) {
15740 33430 merge_threshold_table = DICT_INDEX_MERGE_THRESHOLD_DEFAULT;
15741 }
15742
15743
2/2
✓ Branch 0 taken 241504 times.
✓ Branch 1 taken 401063 times.
642567 for (uint i = 0; i < table_share->keys; i++) {
15744 241504 KEY *key_info = &table_share->key_info[i];
15745
15746
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 241504 times.
241504 ut_ad(i < sizeof(merge_threshold_index) / sizeof(merge_threshold_index[0]));
15747
15748
3/4
✓ Branch 0 taken 236 times.
✓ Branch 1 taken 241268 times.
✓ Branch 2 taken 236 times.
✗ Branch 3 not taken.
241504 if (key_info->flags & HA_USES_COMMENT && key_info->comment.str != nullptr) {
15749 236 merge_threshold_index[i] =
15750
1/2
✓ Branch 0 taken 236 times.
✗ Branch 1 not taken.
236 innobase_parse_merge_threshold(thd, key_info->comment.str);
15751 } else {
15752 241268 merge_threshold_index[i] = merge_threshold_table;
15753 }
15754
15755
2/2
✓ Branch 0 taken 190 times.
✓ Branch 1 taken 241314 times.
241504 if (merge_threshold_index[i] == 0) {
15756 190 merge_threshold_index[i] = merge_threshold_table;
15757 }
15758 }
15759
15760
2/2
✓ Branch 0 taken 241504 times.
✓ Branch 1 taken 401063 times.
642567 for (uint i = 0; i < table_share->keys; i++) {
15761 241504 is_found[i] = false;
15762 }
15763
15764 /* update in memory */
15765
6/10
✓ Branch 0 taken 401063 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 401063 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 505085 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 906148 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 505085 times.
✓ Branch 9 taken 401063 times.
906148 for (auto index : table->indexes) {
15766
2/2
✓ Branch 0 taken 262627 times.
✓ Branch 1 taken 242458 times.
505085 if (dict_index_is_auto_gen_clust(index)) {
15767 /* GEN_CLUST_INDEX should use merge_threshold_table */
15768
15769 /* x-lock index is needed to exclude concurrent
15770 pessimistic tree operations */
15771
2/4
✓ Branch 0 taken 262627 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 262627 times.
✗ Branch 3 not taken.
262627 rw_lock_x_lock(dict_index_get_lock(index), UT_LOCATION_HERE);
15772 262627 index->merge_threshold = merge_threshold_table;
15773
2/4
✓ Branch 0 taken 262627 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 262627 times.
✗ Branch 3 not taken.
262627 rw_lock_x_unlock(dict_index_get_lock(index));
15774
15775 262627 continue;
15776 }
15777
15778
2/2
✓ Branch 0 taken 513376 times.
✓ Branch 1 taken 978 times.
514354 for (uint i = 0; i < table_share->keys; i++) {
15779
2/2
✓ Branch 0 taken 269910 times.
✓ Branch 1 taken 243466 times.
513376 if (is_found[i]) {
15780 269910 continue;
15781 }
15782
15783 243466 KEY *key_info = &table_share->key_info[i];
15784
15785
3/4
✓ Branch 0 taken 243466 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 241480 times.
✓ Branch 3 taken 1986 times.
243466 if (innobase_strcasecmp(index->name, key_info->name) == 0) {
15786 /* x-lock index is needed to exclude concurrent
15787 pessimistic tree operations */
15788
2/4
✓ Branch 0 taken 241480 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 241480 times.
✗ Branch 3 not taken.
241480 rw_lock_x_lock(dict_index_get_lock(index), UT_LOCATION_HERE);
15789 241480 index->merge_threshold = merge_threshold_index[i];
15790
2/4
✓ Branch 0 taken 241480 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 241480 times.
✗ Branch 3 not taken.
241480 rw_lock_x_unlock(dict_index_get_lock(index));
15791 241480 is_found[i] = true;
15792
15793 241480 break;
15794 }
15795 }
15796 }
15797 401063 }
15798
15799 /** Set m_use_* flags. */
15800 412514 void create_table_info_t::set_tablespace_type(
15801 bool table_being_altered_is_file_per_table) {
15802 /* Note whether this table will be created using a shared,
15803 general or system tablespace. */
15804 412514 m_use_shared_space = tablespace_is_shared_space(m_create_info);
15805
15806 /** Allow file_per_table for this table either because:
15807 1) the setting innodb_file_per_table=on,
15808 2) the table being altered is currently file_per_table
15809 3) explicitly requested by tablespace=innodb_file_per_table. */
15810
1/2
✓ Branch 0 taken 25280 times.
✗ Branch 1 not taken.
25280 m_allow_file_per_table = m_innodb_file_per_table ||
15811
4/4
✓ Branch 0 taken 25280 times.
✓ Branch 1 taken 387234 times.
✓ Branch 2 taken 136 times.
✓ Branch 3 taken 25144 times.
437794 table_being_altered_is_file_per_table ||
15812 25280 tablespace_is_file_per_table(m_create_info);
15813
15814 412514 bool is_temp = m_create_info->options & HA_LEX_CREATE_TMP_TABLE;
15815
15816 /* Ignore the current innodb_file_per_table setting if we are
15817 creating a temporary table or if the
15818 TABLESPACE= phrase is using an existing shared tablespace. */
15819 412514 m_use_file_per_table =
15820
6/6
✓ Branch 0 taken 387371 times.
✓ Branch 1 taken 25143 times.
✓ Branch 2 taken 234054 times.
✓ Branch 3 taken 153317 times.
✓ Branch 4 taken 209573 times.
✓ Branch 5 taken 24481 times.
412514 m_allow_file_per_table && !is_temp && !m_use_shared_space;
15821
15822 /* DATA DIRECTORY must have m_use_file_per_table. */
15823 1034602 m_use_data_dir = m_use_file_per_table &&
15824
4/4
✓ Branch 0 taken 209574 times.
✓ Branch 1 taken 202940 times.
✓ Branch 2 taken 20679 times.
✓ Branch 3 taken 188895 times.
433193 (m_create_info->data_file_name != nullptr) &&
15825
2/2
✓ Branch 0 taken 645 times.
✓ Branch 1 taken 20034 times.
20679 (m_create_info->data_file_name[0] != '\0');
15826
4/6
✓ Branch 0 taken 44844 times.
✓ Branch 1 taken 367670 times.
✓ Branch 2 taken 44844 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 412515 times.
412514 ut_ad(!(m_use_shared_space && m_use_data_dir));
15827 412515 }
15828
15829 /** Initialize the create_table_info_t object.
15830 @return error number */
15831 325062 int create_table_info_t::initialize() {
15832
1/2
✓ Branch 0 taken 325063 times.
✗ Branch 1 not taken.
325062 DBUG_TRACE;
15833
15834
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 325063 times.
325063 ut_ad(m_thd != nullptr);
15835
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 325062 times.
325063 ut_ad(m_create_info != nullptr);
15836
15837
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 325052 times.
325062 if (m_form->s->fields > REC_MAX_N_USER_FIELDS) {
15838 10 return HA_ERR_TOO_MANY_FIELDS;
15839 }
15840
15841
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 325053 times.
325052 ut_ad(m_form->s->row_type == m_create_info->row_type);
15842
15843 /* Check for name conflicts (with reserved name) for
15844 any user indices to be created. */
15845
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 325050 times.
325052 if (innobase_index_name_is_reserved(m_thd, m_form->key_info,
15846
1/2
✓ Branch 0 taken 325052 times.
✗ Branch 1 not taken.
325053 m_form->s->keys)) {
15847 2 return HA_ERR_WRONG_INDEX;
15848 }
15849
15850 325050 m_trx->will_lock++;
15851
15852 325050 m_table = nullptr;
15853
15854 325050 return 0;
15855 325062 }
15856
15857 /** Initialize the autoinc of this table if necessary, which should
15858 be called before we flush logs, so autoinc counter can be persisted. */
15859 347993 void create_table_info_t::initialize_autoinc() {
15860 dict_table_t *innobase_table;
15861
15862
2/2
✓ Branch 0 taken 194477 times.
✓ Branch 1 taken 153516 times.
542470 const bool persist = !(m_create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
15863
2/2
✓ Branch 0 taken 15712 times.
✓ Branch 1 taken 178765 times.
194477 m_form->found_next_number_field;
15864
15865
4/4
✓ Branch 0 taken 332281 times.
✓ Branch 1 taken 15712 times.
✓ Branch 2 taken 331502 times.
✓ Branch 3 taken 779 times.
347993 if (!persist && m_create_info->auto_increment_value == 0) {
15866 331502 return;
15867 }
15868
15869 innobase_table =
15870 16491 thd_to_innodb_session(m_thd)->lookup_table_handler(m_table_name);
15871
15872
1/2
✓ Branch 0 taken 16491 times.
✗ Branch 1 not taken.
16491 if (innobase_table == nullptr) {
15873 16491 innobase_table = dd_table_open_on_name_in_mem(m_table_name, false);
15874 } else {
15875 innobase_table->acquire();
15876 ut_ad(innobase_table->is_intrinsic());
15877 }
15878
15879
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16491 times.
16491 assert(innobase_table != nullptr);
15880
15881
2/2
✓ Branch 0 taken 15712 times.
✓ Branch 1 taken 779 times.
16491 if (persist) {
15882 15712 dict_table_autoinc_set_col_pos(
15883 15712 innobase_table, m_form->found_next_number_field->field_index());
15884
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15712 times.
15712 ut_ad(dict_table_has_autoinc_col(innobase_table));
15885 }
15886
15887 /* We need to copy the AUTOINC value from the old table if
15888 this is an ALTER|OPTIMIZE TABLE or CREATE INDEX because CREATE INDEX
15889 does a table copy too. If query was one of :
15890
15891 CREATE TABLE ...AUTO_INCREMENT = x; or
15892 ALTER TABLE...AUTO_INCREMENT = x; or
15893 OPTIMIZE TABLE t; or
15894 CREATE INDEX x on t(...);
15895
15896 Find out a table definition from the dictionary and get
15897 the current value of the auto increment field. Set a new
15898 value to the auto increment field if the value is greater
15899 than the maximum value in the column. */
15900
15901 16491 enum_sql_command cmd = static_cast<enum_sql_command>(thd_sql_command(m_thd));
15902
15903
2/2
✓ Branch 0 taken 2102 times.
✓ Branch 1 taken 14389 times.
16491 if (m_create_info->auto_increment_value > 0 &&
15904
4/4
✓ Branch 0 taken 1628 times.
✓ Branch 1 taken 474 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 1622 times.
2102 ((m_create_info->used_fields & HA_CREATE_USED_AUTO) ||
15905
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
6 cmd == SQLCOM_ALTER_TABLE || cmd == SQLCOM_OPTIMIZE ||
15906 cmd == SQLCOM_CREATE_INDEX)) {
15907 uint64_t auto_inc_value;
15908
15909 2101 auto_inc_value = m_create_info->auto_increment_value;
15910
15911 2101 dict_table_autoinc_lock(innobase_table);
15912 2101 dict_table_autoinc_initialize(innobase_table, auto_inc_value);
15913 2101 dict_table_autoinc_unlock(innobase_table);
15914 }
15915
15916 16491 dd_table_close(innobase_table, nullptr, nullptr, false);
15917 }
15918
15919 /** Prepare to create a new table to an InnoDB database.
15920 @param[in] name Table name
15921 @return error number */
15922 352410 int create_table_info_t::prepare_create_table(const char *name) {
15923
1/2
✓ Branch 0 taken 352411 times.
✗ Branch 1 not taken.
352410 DBUG_TRACE;
15924
15925
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 352411 times.
352411 ut_ad(m_thd != nullptr);
15926
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 352411 times.
352411 ut_ad(m_form->s->row_type == m_create_info->row_type);
15927
15928
2/4
✓ Branch 0 taken 352410 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 352410 times.
352411 if (!normalize_table_name(m_table_name, name)) {
15929 /* purecov: begin inspected */
15930 ut_d(ut_error);
15931 ut_o(return (HA_ERR_TOO_LONG_PATH));
15932 /* purecov: end */
15933 }
15934
15935
1/2
✓ Branch 0 taken 352411 times.
✗ Branch 1 not taken.
352410 set_tablespace_type(false);
15936
15937 /* Validate the create options if innodb_strict_mode is set.
15938 Do not use the regular message for ER_ILLEGAL_HA_CREATE_OPTION
15939 because InnoDB might actually support the option, but not under
15940 the current conditions. The messages revealing the specific
15941 problems are reported inside this function. */
15942
3/4
✓ Branch 0 taken 352411 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 168 times.
✓ Branch 3 taken 352243 times.
352411 if (create_options_are_invalid()) {
15943 168 return HA_WRONG_CREATE_OPTION;
15944 }
15945
15946 /* Create the table flags and flags2 */
15947
6/6
✓ Branch 0 taken 336005 times.
✓ Branch 1 taken 16238 times.
✓ Branch 2 taken 335991 times.
✓ Branch 3 taken 13 times.
✓ Branch 4 taken 335992 times.
✓ Branch 5 taken 16250 times.
352243 if (flags() == 0 && flags2() == 0) {
15948
3/4
✓ Branch 0 taken 335990 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 335989 times.
335992 if (!innobase_table_flags()) {
15949 1 return HA_WRONG_CREATE_OPTION;
15950 }
15951 }
15952
15953
5/8
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 352157 times.
✓ Branch 2 taken 82 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 82 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 352241 times.
352239 ut_ad(!high_level_read_only || is_intrinsic_temp_table());
15954
15955
1/2
✓ Branch 0 taken 352241 times.
✗ Branch 1 not taken.
352241 return parse_table_name(name);
15956 352410 }
15957
15958 /** Check a column (name) is a base column for any stored column in the table
15959 @param[in] table TABLE* for the table
15960 @param[in] name column name to check
15961 @return true if this is a base column */
15962 1004 static bool innobase_is_base_s_col(const TABLE *table, const char *name) {
15963
2/2
✓ Branch 0 taken 1576 times.
✓ Branch 1 taken 988 times.
2564 for (uint i = 0; i < table->s->fields; ++i) {
15964 1576 const Field *field = table->field[i];
15965
15966
2/2
✓ Branch 0 taken 1558 times.
✓ Branch 1 taken 18 times.
1576 if (!innobase_is_s_fld(field)) {
15967 1558 continue;
15968 }
15969
15970
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 2 times.
25 for (uint j = 0; j < table->s->fields; ++j) {
15971
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 5 times.
23 if (bitmap_is_set(&field->gcol_info->base_columns_map, j)) {
15972 18 const Field *base_field = table->field[j];
15973
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
18 if (innobase_strcasecmp(base_field->field_name, name) == 0) {
15974 16 return (true);
15975 }
15976 }
15977 }
15978 }
15979
15980 988 return (false);
15981 }
15982
15983 /** Check any cascading foreign key columns are base columns
15984 for any stored columns in the table
15985 @param[in] dd_table dd::Table for the table
15986 @param[in] table TABLE* for the table
15987 @return DB_NO_FK_ON_S_BASE_COL if found or DB_SUCCESS */
15988 237262 static dberr_t innobase_check_fk_base_col(const dd::Table *dd_table,
15989 const TABLE *table) {
15990
6/10
✓ Branch 0 taken 237264 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 237264 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 237264 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 19075 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 19075 times.
✓ Branch 9 taken 237247 times.
256321 for (const dd::Foreign_key *key : dd_table->foreign_keys()) {
15991 19075 bool upd_cascade = false;
15992 19075 bool del_cascade = false;
15993
15994
3/5
✓ Branch 0 taken 19075 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 819 times.
✓ Branch 3 taken 18256 times.
✗ Branch 4 not taken.
19075 switch (key->update_rule()) {
15995 819 case dd::Foreign_key::RULE_CASCADE:
15996 case dd::Foreign_key::RULE_SET_NULL:
15997 819 upd_cascade = true;
15998 819 break;
15999 18256 case dd::Foreign_key::RULE_NO_ACTION:
16000 case dd::Foreign_key::RULE_RESTRICT:
16001 case dd::Foreign_key::RULE_SET_DEFAULT:
16002 18256 break;
16003 }
16004
16005
3/5
✓ Branch 0 taken 19075 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 215 times.
✓ Branch 3 taken 18860 times.
✗ Branch 4 not taken.
19075 switch (key->delete_rule()) {
16006 215 case dd::Foreign_key::RULE_CASCADE:
16007 case dd::Foreign_key::RULE_SET_NULL:
16008 215 del_cascade = true;
16009 215 break;
16010 18860 case dd::Foreign_key::RULE_NO_ACTION:
16011 case dd::Foreign_key::RULE_RESTRICT:
16012 case dd::Foreign_key::RULE_SET_DEFAULT:
16013 18860 break;
16014 }
16015
16016
4/4
✓ Branch 0 taken 18256 times.
✓ Branch 1 taken 819 times.
✓ Branch 2 taken 18081 times.
✓ Branch 3 taken 175 times.
19075 if (!upd_cascade && !del_cascade) {
16017 18081 continue;
16018 }
16019
16020
6/10
✓ Branch 0 taken 994 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 994 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 994 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1004 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1004 times.
✓ Branch 9 taken 978 times.
1982 for (const dd::Foreign_key_element *key_e : key->elements()) {
16021
3/6
✓ Branch 0 taken 1004 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1004 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1004 times.
✗ Branch 5 not taken.
1004 dd::String_type col_name = key_e->column().name();
16022
16023
3/4
✓ Branch 0 taken 1004 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 988 times.
1004 if (innobase_is_base_s_col(table, col_name.c_str())) {
16024 16 return (DB_NO_FK_ON_S_BASE_COL);
16025 }
16026
2/2
✓ Branch 0 taken 988 times.
✓ Branch 1 taken 16 times.
1004 }
16027 }
16028 237247 return (DB_SUCCESS);
16029 }
16030
16031 /** Create the internal innodb table.
16032 @param[in] dd_table dd::Table or nullptr for intrinsic table
16033 @param[in] old_part_table dd::Table from an old partition for partitioned
16034 table, NULL otherwise.
16035 @return 0 or error number */
16036 348239 int create_table_info_t::create_table(const dd::Table *dd_table,
16037 const dd::Table *old_part_table) {
16038 int error;
16039 uint primary_key_no;
16040 uint i;
16041 const char *stmt;
16042 size_t stmt_len;
16043
16044
1/2
✓ Branch 0 taken 348241 times.
✗ Branch 1 not taken.
348239 DBUG_TRACE;
16045
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348241 times.
348241 assert(m_form->s->keys <= MAX_KEY);
16046
16047 /* Check if dd table has hidden fts doc id index.
16048 Note: in case of TRUNCATE a fulltext table with
16049 hidden doc id index. */
16050
2/2
✓ Branch 0 taken 237262 times.
✓ Branch 1 taken 110979 times.
348241 if (dd_table != nullptr) {
16051
1/2
✓ Branch 0 taken 237263 times.
✗ Branch 1 not taken.
237262 dberr_t err = innobase_check_fk_base_col(dd_table, m_form);
16052
16053
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 237247 times.
237263 if (err != DB_SUCCESS) {
16054
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 error = convert_error_code_to_mysql(err, m_flags, nullptr);
16055
16056 16 return error;
16057 }
16058
16059
6/10
✓ Branch 0 taken 237248 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 237248 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 237248 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 309738 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 309736 times.
✓ Branch 9 taken 237248 times.
546983 for (auto index : dd_table->indexes()) {
16060
2/4
✓ Branch 0 taken 309737 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 309736 times.
✗ Branch 3 not taken.
309738 if (my_strcasecmp(system_charset_info, index->name().c_str(),
16061
4/4
✓ Branch 0 taken 470 times.
✓ Branch 1 taken 309266 times.
✓ Branch 2 taken 463 times.
✓ Branch 3 taken 309273 times.
310206 FTS_DOC_ID_INDEX_NAME) == 0 &&
16062
3/4
✓ Branch 0 taken 470 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 463 times.
✓ Branch 3 taken 7 times.
470 index->is_hidden()) {
16063 463 m_flags2 |= DICT_TF2_FTS_ADD_DOC_ID;
16064 }
16065 }
16066 }
16067
16068 /* Look for a primary key */
16069 348227 primary_key_no = m_form->s->primary_key;
16070
16071 /* Our function innobase_get_mysql_key_number_for_index assumes
16072 the primary key is always number 0, if it exists */
16073
4/6
✓ Branch 0 taken 105729 times.
✓ Branch 1 taken 242498 times.
✓ Branch 2 taken 105729 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 348225 times.
348227 ut_a(primary_key_no == MAX_KEY || primary_key_no == 0);
16074
16075
1/2
✓ Branch 0 taken 348184 times.
✗ Branch 1 not taken.
348225 error = create_table_def(dd_table, old_part_table);
16076
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 348111 times.
348184 if (error) {
16077 73 return error;
16078 }
16079
16080
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348111 times.
348111 ut_ad(m_table != nullptr);
16081
16082 /* Create the keys */
16083
16084
4/4
✓ Branch 0 taken 118816 times.
✓ Branch 1 taken 229295 times.
✓ Branch 2 taken 13149 times.
✓ Branch 3 taken 105667 times.
348111 if (m_form->s->keys == 0 || primary_key_no == MAX_KEY) {
16085 /* Create an index which is used as the clustered index;
16086 order the rows by their row id which is internally generated
16087 by InnoDB */
16088
16089 error =
16090
1/2
✓ Branch 0 taken 242444 times.
✗ Branch 1 not taken.
242444 create_clustered_index_when_no_primary(m_trx, m_flags, m_table_name);
16091
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 242431 times.
242444 if (error) {
16092 13 return error;
16093 }
16094 }
16095
16096
2/2
✓ Branch 0 taken 105667 times.
✓ Branch 1 taken 242431 times.
348098 if (primary_key_no != MAX_KEY) {
16097 /* In InnoDB the clustered index must always be created
16098 first */
16099
1/2
✓ Branch 0 taken 105625 times.
✗ Branch 1 not taken.
105667 error = create_index(m_trx, m_form, m_flags, m_table_name, primary_key_no,
16100 dd_table);
16101
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 105615 times.
105625 if (error) {
16102 10 return error;
16103 }
16104 }
16105
16106 /* Create the ancillary tables that are common to all FTS indexes on
16107 this table. */
16108
2/2
✓ Branch 0 taken 470 times.
✓ Branch 1 taken 347576 times.
348046 if (m_flags2 & (DICT_TF2_FTS | DICT_TF2_FTS_ADD_DOC_ID)) {
16109 fts_doc_id_index_enum ret;
16110
16111 /* Check whether there already exists FTS_DOC_ID_INDEX */
16112 940 ret = innobase_fts_check_doc_id_index_in_def(m_form->s->keys,
16113
1/2
✓ Branch 0 taken 470 times.
✗ Branch 1 not taken.
470 m_form->key_info);
16114
16115
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 470 times.
✗ Branch 2 not taken.
470 switch (ret) {
16116 case FTS_INCORRECT_DOC_ID_INDEX:
16117 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
16118 ER_WRONG_NAME_FOR_INDEX,
16119 " InnoDB: Index name %s is reserved"
16120 " for the unique index on"
16121 " FTS_DOC_ID column for FTS"
16122 " Document ID indexing"
16123 " on table %s. Please check"
16124 " the index definition to"
16125 " make sure it is of correct"
16126 " type\n",
16127 FTS_DOC_ID_INDEX_NAME, m_table->name.m_name);
16128
16129 if (m_table->fts) {
16130 fts_free(m_table);
16131 }
16132
16133 my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), FTS_DOC_ID_INDEX_NAME);
16134 error = -1;
16135 return error;
16136 470 case FTS_EXIST_DOC_ID_INDEX:
16137 case FTS_NOT_EXIST_DOC_ID_INDEX:
16138 470 break;
16139 }
16140
16141
1/2
✓ Branch 0 taken 470 times.
✗ Branch 1 not taken.
470 dberr_t err = fts_create_common_tables(m_trx, m_table, m_table_name,
16142 (ret == FTS_EXIST_DOC_ID_INDEX));
16143
16144
1/2
✓ Branch 0 taken 470 times.
✗ Branch 1 not taken.
470 error = convert_error_code_to_mysql(err, 0, nullptr);
16145
16146 470 DICT_TF2_FLAG_UNSET(m_table, DICT_TF2_FTS_ADD_DOC_ID);
16147
16148
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 466 times.
470 if (error) {
16149 4 return error;
16150 }
16151 }
16152
16153
2/2
✓ Branch 0 taken 179512 times.
✓ Branch 1 taken 347993 times.
527505 for (i = 0; i < m_form->s->keys; i++) {
16154
2/2
✓ Branch 0 taken 73899 times.
✓ Branch 1 taken 105613 times.
179512 if (i != primary_key_no) {
16155
1/2
✓ Branch 0 taken 73858 times.
✗ Branch 1 not taken.
73899 error = create_index(m_trx, m_form, m_flags, m_table_name, i, dd_table);
16156
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 73850 times.
73858 if (error) {
16157 8 return error;
16158 }
16159 }
16160 }
16161
16162
1/2
✓ Branch 0 taken 347993 times.
✗ Branch 1 not taken.
347993 initialize_autoinc();
16163
16164 /* Cache all the FTS indexes on this table in the FTS specific
16165 structure. They are used for FTS indexed column update handling. */
16166
2/2
✓ Branch 0 taken 457 times.
✓ Branch 1 taken 347536 times.
347993 if (m_flags2 & DICT_TF2_FTS) {
16167 457 fts_t *fts = m_table->fts;
16168
16169
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 457 times.
457 ut_a(fts != nullptr);
16170
16171
1/2
✓ Branch 0 taken 457 times.
✗ Branch 1 not taken.
457 dict_table_get_all_fts_indexes(m_table, fts->indexes);
16172 }
16173
16174
1/2
✓ Branch 0 taken 347993 times.
✗ Branch 1 not taken.
347993 stmt = innobase_get_stmt_unsafe(m_thd, &stmt_len);
16175
16176
1/2
✓ Branch 0 taken 347993 times.
✗ Branch 1 not taken.
347993 innodb_session_t *&priv = thd_to_innodb_session(m_trx->mysql_thd);
16177
1/2
✓ Branch 0 taken 347993 times.
✗ Branch 1 not taken.
347993 dict_table_t *handler = priv->lookup_table_handler(m_table_name);
16178
16179
5/8
✓ Branch 0 taken 110974 times.
✓ Branch 1 taken 237019 times.
✓ Branch 2 taken 110974 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 110974 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 347993 times.
347993 ut_ad(handler == nullptr || handler->is_intrinsic());
16180
5/8
✓ Branch 0 taken 110974 times.
✓ Branch 1 taken 237019 times.
✓ Branch 2 taken 110974 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 110974 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 347993 times.
347993 ut_ad(handler == nullptr || is_intrinsic_temp_table());
16181
16182 /* There is no concept of foreign key for intrinsic tables. */
16183
4/6
✓ Branch 0 taken 237019 times.
✓ Branch 1 taken 110974 times.
✓ Branch 2 taken 237019 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 237019 times.
✗ Branch 5 not taken.
347993 if (handler == nullptr && stmt != nullptr && dd_table != nullptr
16184 /* FIXME: NewDD: WL#6049 should add a new call to check if a table
16185 is a parent table of any FK. If the table is not child table, nor
16186 parent table, then it can skip the check:
16187 dd_table->foreign_keys().empty() &&
16188 dd_table->referenced_keys().empty() */
16189 ) {
16190 237019 dberr_t err = DB_SUCCESS;
16191
16192
1/2
✓ Branch 0 taken 237019 times.
✗ Branch 1 not taken.
237019 dict_sys_mutex_enter();
16193
1/2
✓ Branch 0 taken 237019 times.
✗ Branch 1 not taken.
237019 err = row_table_load_foreign_constraints(m_trx, m_table_name, dd_table);
16194
1/2
✓ Branch 0 taken 237019 times.
✗ Branch 1 not taken.
237019 dict_sys_mutex_exit();
16195
16196
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 237019 times.
237019 switch (err) {
16197 case DB_PARENT_NO_INDEX:
16198 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
16199 HA_ERR_CANNOT_ADD_FOREIGN,
16200 "Create table '%s' with foreign key constraint"
16201 " failed. There is no index in the referenced"
16202 " table where the referenced columns appear"
16203 " as the first columns.\n",
16204 m_table_name);
16205 break;
16206
16207 case DB_CHILD_NO_INDEX:
16208 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
16209 HA_ERR_CANNOT_ADD_FOREIGN,
16210 "Create table '%s' with foreign key constraint"
16211 " failed. There is no index in the referencing"
16212 " table where referencing columns appear"
16213 " as the first columns.\n",
16214 m_table_name);
16215 break;
16216 case DB_NO_FK_ON_S_BASE_COL:
16217 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
16218 HA_ERR_CANNOT_ADD_FOREIGN,
16219 "Create table '%s' with foreign key constraint"
16220 " failed. Cannot add foreign key constraint"
16221 " placed on the base column of stored"
16222 " column.\n",
16223 m_table_name);
16224 break;
16225 237019 default:
16226 237019 break;
16227 }
16228
16229
1/2
✓ Branch 0 taken 237019 times.
✗ Branch 1 not taken.
237019 error = convert_error_code_to_mysql(err, m_flags, nullptr);
16230
16231
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 237017 times.
237019 if (error) {
16232
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (handler != nullptr) {
16233 priv->unregister_table_handler(m_table_name);
16234 }
16235 2 return error;
16236 }
16237 }
16238
16239 347991 return 0;
16240 348117 }
16241
16242 /** Update a new table in an InnoDB database.
16243 @return error number */
16244 347991 int create_table_info_t::create_table_update_dict() {
16245
1/2
✓ Branch 0 taken 347991 times.
✗ Branch 1 not taken.
347991 DBUG_TRACE;
16246
16247
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 347991 times.
347991 assert(m_table != nullptr);
16248
16249 #ifdef UNIV_DEBUG
16250
3/4
✓ Branch 0 taken 347991 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 110974 times.
✓ Branch 3 taken 237017 times.
347991 if (m_table->is_intrinsic()) {
16251 dict_table_t *innobase_table =
16252
2/4
✓ Branch 0 taken 110974 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 110974 times.
✗ Branch 3 not taken.
110974 thd_to_innodb_session(m_thd)->lookup_table_handler(m_table_name);
16253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 110974 times.
110974 ut_ad(m_table == innobase_table);
16254 }
16255 #endif /* UNIV_DEBUG */
16256
16257 /* Temp table must be uncompressed and reside in tmp tablespace. */
16258
2/4
✓ Branch 0 taken 347991 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 347991 times.
347991 ut_ad(!dict_table_is_compressed_temporary(m_table));
16259
2/2
✓ Branch 0 taken 462 times.
✓ Branch 1 taken 347529 times.
347991 if (m_table->fts != nullptr) {
16260
1/2
✓ Branch 0 taken 462 times.
✗ Branch 1 not taken.
462 if (m_table->fts_doc_id_index == nullptr) {
16261 924 m_table->fts_doc_id_index =
16262
1/2
✓ Branch 0 taken 462 times.
✗ Branch 1 not taken.
462 dict_table_get_index_on_name(m_table, FTS_DOC_ID_INDEX_NAME);
16263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 462 times.
462 assert(m_table->fts_doc_id_index != nullptr);
16264 } else {
16265 assert(m_table->fts_doc_id_index ==
16266 dict_table_get_index_on_name(m_table, FTS_DOC_ID_INDEX_NAME));
16267 }
16268 }
16269
16270
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 347991 times.
347991 assert((m_table->fts == nullptr) == (m_table->fts_doc_id_index == nullptr));
16271
16272
1/2
✓ Branch 0 taken 347991 times.
✗ Branch 1 not taken.
347991 innobase_copy_frm_flags_from_create_info(m_table, m_create_info);
16273
16274
1/2
✓ Branch 0 taken 347991 times.
✗ Branch 1 not taken.
347991 dict_stats_update(m_table, DICT_STATS_EMPTY_TABLE);
16275
16276 /* Since no dict_table_close(), deinitialize it explicitly. */
16277
1/2
✓ Branch 0 taken 347991 times.
✗ Branch 1 not taken.
347991 dict_stats_deinit(m_table);
16278
16279 /* Load server stopword into FTS cache */
16280
2/2
✓ Branch 0 taken 457 times.
✓ Branch 1 taken 347534 times.
347991 if (m_flags2 & DICT_TF2_FTS) {
16281
2/4
✓ Branch 0 taken 457 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 457 times.
457 if (!innobase_fts_load_stopword(m_table, nullptr, m_thd)) {
16282 return -1;
16283 }
16284 }
16285
16286
1/2
✓ Branch 0 taken 347991 times.
✗ Branch 1 not taken.
347991 innobase_parse_hint_from_comment(m_thd, m_table, m_form->s);
16287 347991 return 0;
16288 347991 }
16289
16290 /** Update the global data dictionary.
16291 @param[in] dd_table dd::Table or dd::Partition
16292 @retval 0 On success
16293 @retval error number On failure */
16294 template <typename Table>
16295 695982 int create_table_info_t::create_table_update_global_dd(Table *dd_table) {
16296
1/2
✓ Branch 0 taken 347991 times.
✗ Branch 1 not taken.
695982 DBUG_TRACE;
16297
16298
4/4
✓ Branch 0 taken 237017 times.
✓ Branch 1 taken 110974 times.
✓ Branch 2 taken 42541 times.
✓ Branch 3 taken 194476 times.
695982 if (dd_table == nullptr || (m_flags2 & DICT_TF2_TEMPORARY)) {
16299 /* No need to fill in metadata for all temporary tables.
16300 The Table object for temporary table is either NULL or
16301 a fake one, whose metadata would not be written back later */
16302 307030 return 0;
16303 }
16304
16305
2/2
✓ Branch 0 taken 15712 times.
✓ Branch 1 taken 178764 times.
388952 if (m_form->found_next_number_field != nullptr) {
16306
1/2
✓ Branch 0 taken 15712 times.
✗ Branch 1 not taken.
31424 dd_set_autoinc(dd_table->se_private_data(),
16307
1/2
✓ Branch 0 taken 15712 times.
✗ Branch 1 not taken.
31424 m_create_info->auto_increment_value);
16308 }
16309
16310
1/2
✓ Branch 0 taken 194476 times.
✗ Branch 1 not taken.
388952 dd::cache::Dictionary_client *client = dd::get_dd_client(m_thd);
16311
1/2
✓ Branch 0 taken 194476 times.
✗ Branch 1 not taken.
388952 dd::cache::Dictionary_client::Auto_releaser releaser(client);
16312
16313
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 194476 times.
388952 ut_ad(m_table != nullptr);
16314
2/4
✓ Branch 0 taken 194476 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 194476 times.
388952 ut_ad(!m_table->is_temporary());
16315
16316
1/2
✓ Branch 0 taken 194476 times.
✗ Branch 1 not taken.
388952 bool file_per_table = dict_table_is_file_per_table(m_table);
16317 388952 dd::Object_id dd_space_id = dd::INVALID_OBJECT_ID;
16318 388952 bool is_dd_table = m_table->space == dict_sys_t::s_dict_space_id;
16319
16320
2/2
✓ Branch 0 taken 23004 times.
✓ Branch 1 taken 171472 times.
388952 if (is_dd_table) {
16321 46008 dd_space_id = dict_sys_t::s_dd_dict_space_id;
16322
2/2
✓ Branch 0 taken 4736 times.
✓ Branch 1 taken 166736 times.
342944 } else if (m_table->space == TRX_SYS_SPACE) {
16323 9472 dd_space_id = dict_sys_t::s_dd_sys_space_id;
16324
2/2
✓ Branch 0 taken 165597 times.
✓ Branch 1 taken 1139 times.
333472 } else if (file_per_table) {
16325
1/2
✓ Branch 0 taken 165597 times.
✗ Branch 1 not taken.
331194 char *filename = fil_space_get_first_path(m_table->space);
16326
16327
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165597 times.
331194 if (dd_create_implicit_tablespace(client, m_table->space,
16328
1/2
✓ Branch 0 taken 165597 times.
✗ Branch 1 not taken.
331194 m_table->name.m_name, filename, false,
16329 dd_space_id)) {
16330 ut::free(filename);
16331 return HA_ERR_GENERIC;
16332 }
16333
16334
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165597 times.
331194 ut_ad(dd_space_id != dd::INVALID_OBJECT_ID);
16335 331194 ut::free(filename);
16336 } else {
16337
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1139 times.
2278 ut_ad(DICT_TF_HAS_SHARED_SPACE(m_table->flags));
16338
16339
1/2
✓ Branch 0 taken 1139 times.
✗ Branch 1 not taken.
2278 dd_space_id = dd_get_space_id(*dd_table);
16340
16341 2278 const dd::Tablespace *index_space = nullptr;
16342
2/4
✓ Branch 0 taken 1139 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1139 times.
2278 if (client->acquire<dd::Tablespace>(dd_space_id, &index_space)) {
16343 return HA_ERR_GENERIC;
16344 }
16345
16346
2/4
✓ Branch 0 taken 1139 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1139 times.
2278 DBUG_EXECUTE_IF("create_table_update_dd_fail", index_space = nullptr;);
16347
16348 uint32_t id;
16349
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1139 times.
2278 if (index_space == nullptr) {
16350 my_error(ER_TABLESPACE_MISSING, MYF(0), m_table->name.m_name);
16351 return HA_ERR_TABLESPACE_MISSING;
16352
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1139 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2278 } else if (index_space->se_private_data().get(
16353
5/10
✓ Branch 0 taken 1139 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1139 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1139 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1139 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1139 times.
✗ Branch 9 not taken.
4556 dd_space_key_strings[DD_SPACE_ID], &id) ||
16354
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1139 times.
2278 id != m_table->space) {
16355 ut_ad(!"missing or incorrect tablespace id");
16356 return HA_ERR_GENERIC;
16357 }
16358 }
16359
16360 388952 m_table->dd_space_id = dd_space_id;
16361
16362
1/2
✓ Branch 0 taken 194476 times.
✗ Branch 1 not taken.
388952 dd_set_table_options(dd_table, m_table);
16363
16364
1/2
✓ Branch 0 taken 194476 times.
✗ Branch 1 not taken.
388952 dd_write_table(dd_space_id, dd_table, m_table);
16365
16366
2/2
✓ Branch 0 taken 462 times.
✓ Branch 1 taken 194014 times.
388952 if (m_flags2 & (DICT_TF2_FTS | DICT_TF2_FTS_ADD_DOC_ID)) {
16367
1/2
✓ Branch 0 taken 462 times.
✗ Branch 1 not taken.
924 ut_d(bool ret =) fts_create_common_dd_tables(m_table);
16368
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 462 times.
924 ut_ad(ret);
16369
1/2
✓ Branch 0 taken 462 times.
✗ Branch 1 not taken.
924 fts_create_index_dd_tables(m_table);
16370 }
16371
16372
2/4
✓ Branch 0 taken 194476 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 194476 times.
388952 ut_ad(dd_table_match(m_table, dd_table));
16373
16374 388952 return 0;
16375 695982 }
16376
16377 template int create_table_info_t::create_table_update_global_dd<dd::Table>(
16378 dd::Table *);
16379
16380 template int create_table_info_t::create_table_update_global_dd<dd::Partition>(
16381 dd::Partition *);
16382
16383 template <typename Table>
16384 642126 int innobase_basic_ddl::create_impl(THD *thd, const char *name, TABLE *form,
16385 HA_CREATE_INFO *create_info, Table *dd_tab,
16386 bool file_per_table, bool evictable,
16387 bool skip_strict, uint32_t old_flags,
16388 uint32_t old_flags2,
16389 const dd::Table *old_part_table) {
16390 642126 char norm_name[FN_REFLEN] = {'\0'}; /* {database}/{tablename} */
16391 642126 char remote_path[FN_REFLEN] = {'\0'}; /* Absolute path of table */
16392 642126 char tablespace[NAME_LEN] = {'\0'}; /* Tablespace name identifier */
16393 trx_t *trx;
16394
16395
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 320976 times.
642126 if (high_level_read_only &&
16396
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 82 times.
174 !(create_info->options & HA_LEX_CREATE_INTERNAL_TMP_TABLE)) {
16397 10 return HA_ERR_INNODB_READ_ONLY;
16398 }
16399
16400 /* Get the transaction associated with the current thd, or create one
16401 if not yet created */
16402
1/2
✓ Branch 0 taken 321058 times.
✗ Branch 1 not taken.
642116 trx = check_trx_exists(thd);
16403
16404
2/2
✓ Branch 0 taken 167496 times.
✓ Branch 1 taken 153562 times.
642116 if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) {
16405
1/2
✓ Branch 0 taken 167496 times.
✗ Branch 1 not taken.
334992 trx_start_if_not_started(trx, true, UT_LOCATION_HERE);
16406 }
16407
16408
1/2
✓ Branch 0 taken 321057 times.
✗ Branch 1 not taken.
642116 create_table_info_t info(thd, form, create_info, norm_name, remote_path,
16409 tablespace, file_per_table, skip_strict, old_flags,
16410 old_flags2, false);
16411
16412 /* Initialize the object. */
16413
1/2
✓ Branch 0 taken 321058 times.
✗ Branch 1 not taken.
642114 int error = info.initialize();
16414
16415
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 321048 times.
642116 if (error != 0) {
16416 20 return (error);
16417 }
16418
16419 /* Prepare for create and validate options. */
16420
1/2
✓ Branch 0 taken 321048 times.
✗ Branch 1 not taken.
642096 error = info.prepare_create_table(name);
16421
16422
2/2
✓ Branch 0 taken 157 times.
✓ Branch 1 taken 320891 times.
642096 if (error != 0) {
16423 314 return (error);
16424 }
16425
16426
5/7
✓ Branch 0 taken 209912 times.
✓ Branch 1 taken 110979 times.
✓ Branch 2 taken 7363 times.
✓ Branch 3 taken 313506 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7288 times.
✗ Branch 6 not taken.
641782 error = info.create_table(dd_tab != nullptr ? &dd_tab->table() : nullptr,
16427 old_part_table);
16428
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 320668 times.
641588 if (error) {
16429 252 goto cleanup;
16430 }
16431
16432
1/2
✓ Branch 0 taken 320668 times.
✗ Branch 1 not taken.
641336 error = info.create_table_update_global_dd(dd_tab);
16433
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 320668 times.
641336 if (error) {
16434 goto cleanup;
16435 }
16436
16437
1/2
✓ Branch 0 taken 320668 times.
✗ Branch 1 not taken.
641336 error = info.create_table_update_dict();
16438
16439
9/10
✓ Branch 0 taken 302570 times.
✓ Branch 1 taken 18098 times.
✓ Branch 2 taken 260076 times.
✓ Branch 3 taken 42494 times.
✓ Branch 4 taken 260076 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 149102 times.
✓ Branch 7 taken 110974 times.
✓ Branch 8 taken 149102 times.
✓ Branch 9 taken 171566 times.
641336 if (evictable && !(info.is_temp_table() || info.is_intrinsic_temp_table())) {
16440
1/2
✓ Branch 0 taken 149102 times.
✗ Branch 1 not taken.
298204 info.detach();
16441 }
16442
16443 641336 return (error);
16444
16445 252 cleanup:
16446
7/8
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 123 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 119 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 122 times.
252 if (!info.is_intrinsic_temp_table() && info.is_temp_table()) {
16447
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
8 dict_sys_mutex_enter();
16448
16449
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
8 dict_table_t *table = dict_table_check_if_in_cache_low(norm_name);
16450
16451
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
8 if (table != nullptr) {
16452
3/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
8 for (dict_index_t *index = table->first_index(); index != nullptr;
16453
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 index = index->next()) {
16454
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
4 ut_ad(index->space == table->space);
16455 4 page_no_t root = index->page;
16456 4 index->page = FIL_NULL;
16457
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 dict_drop_temporary_table_index(index, root);
16458 }
16459
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 dict_table_remove_from_cache(table);
16460 }
16461
16462
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
8 dict_sys_mutex_exit();
16463 } else {
16464 dict_table_t *intrinsic_table =
16465
2/4
✓ Branch 0 taken 122 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 122 times.
✗ Branch 3 not taken.
244 thd_to_innodb_session(thd)->lookup_table_handler(info.table_name());
16466
16467
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 121 times.
244 if (intrinsic_table != nullptr) {
16468
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 thd_to_innodb_session(thd)->unregister_table_handler(info.table_name());
16469
16470 for (;;) {
16471 dict_index_t *index;
16472 2 index = UT_LIST_GET_FIRST(intrinsic_table->indexes);
16473
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
2 if (index == nullptr) {
16474 2 break;
16475 }
16476 rw_lock_free(&index->lock);
16477 UT_LIST_REMOVE(intrinsic_table->indexes, index);
16478 dict_mem_index_free(index);
16479 index = nullptr;
16480 }
16481
16482
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
2 dict_mem_table_free(intrinsic_table);
16483 2 intrinsic_table = nullptr;
16484 }
16485 }
16486
16487 252 return (error);
16488 }
16489
16490 template int innobase_basic_ddl::create_impl<dd::Table>(
16491 THD *, const char *, TABLE *, HA_CREATE_INFO *, dd::Table *, bool, bool,
16492 bool, uint32_t, uint32_t, const dd::Table *);
16493
16494 template int innobase_basic_ddl::create_impl<dd::Partition>(
16495 THD *, const char *, TABLE *, HA_CREATE_INFO *, dd::Partition *, bool, bool,
16496 bool, uint32_t, uint32_t, const dd::Table *);
16497
16498 template <typename Table>
16499 635534 int innobase_basic_ddl::delete_impl(THD *thd, const char *name,
16500 const Table *dd_tab, const TABLE *td) {
16501 635534 dberr_t error = DB_SUCCESS;
16502 char norm_name[FN_REFLEN];
16503
16504
2/6
✓ Branch 0 taken 317768 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 317768 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
635534 DBUG_EXECUTE_IF("test_normalize_table_name", test_normalize_table_name(););
16505
4/6
✓ Branch 0 taken 317769 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 317768 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
635536 DBUG_EXECUTE_IF("test_ut_format_name", test_ut_format_name(););
16506
16507 /* Strangely, MySQL passes the table name without the '.frm'
16508 extension, in contrast to ::create */
16509
2/4
✓ Branch 0 taken 317767 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 317767 times.
635538 if (!normalize_table_name(norm_name, name)) {
16510 /* purecov: begin inspected */
16511 ut_d(ut_error);
16512 ut_o(return (HA_ERR_TOO_LONG_PATH));
16513 /* purecov: end */
16514 }
16515
16516
1/2
✓ Branch 0 taken 317771 times.
✗ Branch 1 not taken.
635534 innodb_session_t *&priv = thd_to_innodb_session(thd);
16517
1/2
✓ Branch 0 taken 317771 times.
✗ Branch 1 not taken.
635542 dict_table_t *handler = priv->lookup_table_handler(norm_name);
16518
16519
2/2
✓ Branch 0 taken 110974 times.
✓ Branch 1 taken 206797 times.
635542 if (handler != nullptr) {
16520
6/10
✓ Branch 0 taken 110974 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 110974 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 113086 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 224060 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 113086 times.
✓ Branch 9 taken 110974 times.
670068 for (auto index : handler->indexes) {
16521
2/2
✓ Branch 0 taken 54161 times.
✓ Branch 1 taken 58925 times.
226172 if (index->last_ins_cur) {
16522 /* last_ins_cur and last_sel_cur are allocated together, therefore only
16523 checking last_ins_cur before releasing mtr */
16524
1/2
✓ Branch 0 taken 54161 times.
✗ Branch 1 not taken.
108322 index->last_ins_cur->release();
16525
1/2
✓ Branch 0 taken 54161 times.
✗ Branch 1 not taken.
108322 index->last_sel_cur->release();
16526 }
16527 }
16528
2/2
✓ Branch 0 taken 206791 times.
✓ Branch 1 taken 6 times.
413594 } else if (srv_read_only_mode ||
16529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 206791 times.
413582 srv_force_recovery >= SRV_FORCE_NO_UNDO_LOG_SCAN) {
16530 12 return (HA_ERR_TABLE_READONLY);
16531 }
16532
16533
1/2
✓ Branch 0 taken 317764 times.
✗ Branch 1 not taken.
635530 trx_t *trx = check_trx_exists(thd);
16534
16535
1/2
✓ Branch 0 taken 317765 times.
✗ Branch 1 not taken.
635528 TrxInInnoDB trx_in_innodb(trx);
16536
16537 635530 ulint name_len = strlen(name);
16538
16539
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 317765 times.
635530 ut_a(name_len < 1000);
16540
16541 /* Either the transaction is already flagged as a locking transaction
16542 or it hasn't been started yet. */
16543
16544
5/8
✓ Branch 0 taken 317764 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 138096 times.
✓ Branch 3 taken 179668 times.
✓ Branch 4 taken 138096 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 317766 times.
635530 ut_a(!trx_is_started(trx) || trx->will_lock > 0);
16545
16546 /* We are doing a DDL operation. */
16547 635532 ++trx->will_lock;
16548
16549 635532 bool file_per_table = false;
16550
7/8
✓ Branch 0 taken 206791 times.
✓ Branch 1 taken 110975 times.
✓ Branch 2 taken 206790 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 164264 times.
✓ Branch 5 taken 42526 times.
✓ Branch 6 taken 164264 times.
✓ Branch 7 taken 153501 times.
635532 if (dd_tab != nullptr && dd_tab->is_persistent()) {
16551 dict_table_t *tab;
16552
16553
1/2
✓ Branch 0 taken 164264 times.
✗ Branch 1 not taken.
328528 dd::cache::Dictionary_client *client = dd::get_dd_client(thd);
16554
1/2
✓ Branch 0 taken 164264 times.
✗ Branch 1 not taken.
328528 dd::cache::Dictionary_client::Auto_releaser releaser(client);
16555
16556
2/3
✓ Branch 0 taken 34678 times.
✓ Branch 1 taken 129586 times.
✗ Branch 2 not taken.
397884 int err = dd_table_open_on_dd_obj(
16557
1/2
✓ Branch 0 taken 34678 times.
✗ Branch 1 not taken.
69356 thd, client, dd_tab->table(),
16558
5/7
✓ Branch 0 taken 34678 times.
✓ Branch 1 taken 129586 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 34678 times.
✓ Branch 4 taken 129586 times.
✓ Branch 5 taken 34678 times.
✗ Branch 6 not taken.
328528 (!dd_table_is_partitioned(dd_tab->table())
16559 ? nullptr
16560 : reinterpret_cast<const dd::Partition *>(dd_tab)),
16561 norm_name, tab, td);
16562
16563
2/4
✓ Branch 0 taken 164264 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 164264 times.
✗ Branch 3 not taken.
328528 if (err == 0 && tab != nullptr) {
16564
10/11
✓ Branch 0 taken 130034 times.
✓ Branch 1 taken 34230 times.
✓ Branch 2 taken 16867 times.
✓ Branch 3 taken 113167 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 16867 times.
✓ Branch 6 taken 113167 times.
✓ Branch 7 taken 16867 times.
✓ Branch 8 taken 129586 times.
✓ Branch 9 taken 16867 times.
✓ Branch 10 taken 17811 times.
328528 if (tab->can_be_evicted && dd_table_is_partitioned(dd_tab->table())) {
16565
1/2
✓ Branch 0 taken 16867 times.
✗ Branch 1 not taken.
33734 dict_sys_mutex_enter();
16566
1/2
✓ Branch 0 taken 16867 times.
✗ Branch 1 not taken.
33734 dict_table_ddl_acquire(tab);
16567
1/2
✓ Branch 0 taken 16867 times.
✗ Branch 1 not taken.
33734 dict_sys_mutex_exit();
16568 }
16569
16570
1/2
✓ Branch 0 taken 164264 times.
✗ Branch 1 not taken.
328528 file_per_table = dict_table_is_file_per_table(tab);
16571
1/2
✓ Branch 0 taken 164264 times.
✗ Branch 1 not taken.
328528 dd_table_close(tab, thd, nullptr, false);
16572 }
16573 328528 }
16574
16575
1/2
✓ Branch 0 taken 317733 times.
✗ Branch 1 not taken.
635530 error = row_drop_table_for_mysql(norm_name, trx, true, handler);
16576
16577
3/4
✓ Branch 0 taken 110974 times.
✓ Branch 1 taken 206759 times.
✓ Branch 2 taken 110974 times.
✗ Branch 3 not taken.
635466 if (handler != nullptr && error == DB_SUCCESS) {
16578
1/2
✓ Branch 0 taken 110974 times.
✗ Branch 1 not taken.
221948 priv->unregister_table_handler(norm_name);
16579 }
16580
16581
4/4
✓ Branch 0 taken 317731 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 152951 times.
✓ Branch 3 taken 164780 times.
635466 if (error == DB_SUCCESS && file_per_table) {
16582
2/4
✓ Branch 0 taken 152951 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 152951 times.
✗ Branch 3 not taken.
305902 dd::Object_id dd_space_id = dd_first_index(dd_tab)->tablespace_id();
16583
1/2
✓ Branch 0 taken 152951 times.
✗ Branch 1 not taken.
305902 dd::cache::Dictionary_client *client = dd::get_dd_client(thd);
16584
1/2
✓ Branch 0 taken 152951 times.
✗ Branch 1 not taken.
305902 dd::cache::Dictionary_client::Auto_releaser releaser(client);
16585
16586
3/4
✓ Branch 0 taken 152951 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 152949 times.
305902 if (dd_drop_tablespace(client, dd_space_id)) {
16587 4 error = DB_ERROR;
16588 }
16589 305902 }
16590
16591
1/2
✓ Branch 0 taken 317733 times.
✗ Branch 1 not taken.
635466 return (convert_error_code_to_mysql(error, 0, nullptr));
16592 635466 }
16593
16594 template int innobase_basic_ddl::delete_impl<dd::Table>(THD *, const char *,
16595 const dd::Table *,
16596 const TABLE *);
16597
16598 template int innobase_basic_ddl::delete_impl<dd::Partition>(
16599 THD *, const char *, const dd::Partition *, const TABLE *);
16600
16601 template <typename Table>
16602 56852 int innobase_basic_ddl::rename_impl(THD *thd, const char *from, const char *to,
16603 const Table *from_table,
16604 const Table *to_table, const TABLE *td) {
16605 dberr_t error;
16606 char norm_to[FN_REFLEN];
16607 char norm_from[FN_REFLEN];
16608 56852 bool rename_file = false;
16609 56852 space_id_t space = SPACE_UNKNOWN;
16610 56852 dict_table_t *table = nullptr;
16611
16612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28426 times.
56852 ut_ad(!srv_read_only_mode);
16613
16614
3/6
✓ Branch 0 taken 28426 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28426 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 28426 times.
113704 if (!normalize_table_name(norm_to, to) ||
16615
2/4
✓ Branch 0 taken 28426 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 28426 times.
56852 !normalize_table_name(norm_from, from)) {
16616 /* purecov: begin inspected */
16617 ut_d(ut_error);
16618 ut_o(return (HA_ERR_TOO_LONG_PATH));
16619 /* purecov: end */
16620 }
16621
16622
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28426 times.
56852 ut_ad(strcmp(norm_from, norm_to) != 0);
16623
16624
3/4
✓ Branch 0 taken 28168 times.
✓ Branch 1 taken 258 times.
✓ Branch 2 taken 28168 times.
✗ Branch 3 not taken.
56852 DEBUG_SYNC_C("innodb_rename_table_ready");
16625
16626
1/2
✓ Branch 0 taken 28426 times.
✗ Branch 1 not taken.
56852 trx_t *trx = check_trx_exists(thd);
16627
16628
1/2
✓ Branch 0 taken 28426 times.
✗ Branch 1 not taken.
56852 trx_start_if_not_started(trx, true, UT_LOCATION_HERE);
16629
16630
1/2
✓ Branch 0 taken 28426 times.
✗ Branch 1 not taken.
56852 TrxInInnoDB trx_in_innodb(trx);
16631
16632 56852 ++trx->will_lock;
16633
16634
1/2
✓ Branch 0 taken 28426 times.
✗ Branch 1 not taken.
56852 dd::cache::Dictionary_client *client = dd::get_dd_client(thd);
16635
1/2
✓ Branch 0 taken 28426 times.
✗ Branch 1 not taken.
56852 dd::cache::Dictionary_client::Auto_releaser releaser(client);
16636
16637
2/3
✓ Branch 0 taken 11317 times.
✓ Branch 1 taken 17109 times.
✗ Branch 2 not taken.
79486 int err = dd_table_open_on_dd_obj(
16638
1/2
✓ Branch 0 taken 11317 times.
✗ Branch 1 not taken.
22634 thd, client, from_table->table(),
16639
5/7
✓ Branch 0 taken 11317 times.
✓ Branch 1 taken 17109 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11317 times.
✓ Branch 4 taken 17109 times.
✓ Branch 5 taken 11317 times.
✗ Branch 6 not taken.
56852 (!dd_table_is_partitioned(from_table->table())
16640 ? nullptr
16641 : reinterpret_cast<const dd::Partition *>(from_table)),
16642 norm_from, table, td);
16643
2/4
✓ Branch 0 taken 28426 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 28426 times.
56852 if (err != 0 || table == nullptr) {
16644 error = DB_TABLE_NOT_FOUND;
16645 return (convert_error_code_to_mysql(error, 0, nullptr));
16646 }
16647
16648
1/2
✓ Branch 0 taken 28426 times.
✗ Branch 1 not taken.
56852 rename_file = dict_table_is_file_per_table(table);
16649 56852 space = table->space;
16650
16651
1/2
✓ Branch 0 taken 28426 times.
✗ Branch 1 not taken.
56852 if (row_is_mysql_tmp_table_name(norm_from) &&
16652
6/8
✓ Branch 0 taken 10916 times.
✓ Branch 1 taken 17510 times.
✓ Branch 2 taken 10916 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10916 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 7139 times.
✓ Branch 7 taken 21287 times.
78684 !row_is_mysql_tmp_table_name(norm_to) &&
16653
4/7
✓ Branch 0 taken 3777 times.
✓ Branch 1 taken 7139 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10916 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 3777 times.
21832 !dd_table_is_partitioned(from_table->table())) {
16654 14278 table->refresh_fk = true;
16655 }
16656
16657
5/7
✓ Branch 0 taken 11317 times.
✓ Branch 1 taken 17109 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11317 times.
✓ Branch 4 taken 17109 times.
✓ Branch 5 taken 11317 times.
✗ Branch 6 not taken.
56852 if (dd_table_is_partitioned(from_table->table())) {
16658
1/2
✓ Branch 0 taken 11317 times.
✗ Branch 1 not taken.
22634 dict_sys_mutex_enter();
16659
1/2
✓ Branch 0 taken 11317 times.
✗ Branch 1 not taken.
22634 dict_table_ddl_acquire(table);
16660
1/2
✓ Branch 0 taken 11317 times.
✗ Branch 1 not taken.
22634 dict_sys_mutex_exit();
16661 }
16662
16663
1/2
✓ Branch 0 taken 28426 times.
✗ Branch 1 not taken.
56852 dd_table_close(table, thd, nullptr, false);
16664
16665 /* Serialize data dictionary operations with dictionary mutex:
16666 no deadlocks can occur then in these operations. */
16667
16668
1/2
✓ Branch 0 taken 28426 times.
✗ Branch 1 not taken.
56852 row_mysql_lock_data_dictionary(trx, UT_LOCATION_HERE);
16669
16670
3/5
✓ Branch 0 taken 11317 times.
✓ Branch 1 taken 17058 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11266 times.
✗ Branch 4 not taken.
56852 error = row_rename_table_for_mysql(norm_from, norm_to, &to_table->table(),
16671 trx, false);
16672
16673
1/2
✓ Branch 0 taken 28324 times.
✗ Branch 1 not taken.
56648 row_mysql_unlock_data_dictionary(trx);
16674
16675
4/4
✓ Branch 0 taken 28306 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 21566 times.
✓ Branch 3 taken 6740 times.
56648 if (error == DB_SUCCESS && rename_file) {
16676
1/2
✓ Branch 0 taken 21566 times.
✗ Branch 1 not taken.
43132 char *new_path = fil_space_get_first_path(space);
16677
16678
2/4
✓ Branch 0 taken 21566 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21566 times.
✗ Branch 3 not taken.
43132 auto dd_space_id = dd_first_index(to_table)->tablespace_id();
16679
16680
1/2
✓ Branch 0 taken 21566 times.
✗ Branch 1 not taken.
43132 error = dd_tablespace_rename(dd_space_id, false, norm_to, new_path);
16681
16682
2/2
✓ Branch 0 taken 21550 times.
✓ Branch 1 taken 16 times.
43132 if (new_path != nullptr) {
16683 43100 ut::free(new_path);
16684 }
16685 }
16686
16687
3/4
✓ Branch 0 taken 28066 times.
✓ Branch 1 taken 258 times.
✓ Branch 2 taken 28066 times.
✗ Branch 3 not taken.
56648 DEBUG_SYNC(thd, "after_innobase_rename_table");
16688
16689
2/2
✓ Branch 0 taken 28306 times.
✓ Branch 1 taken 18 times.
56648 if (error == DB_SUCCESS) {
16690 char errstr[512];
16691 dberr_t ret;
16692
16693
1/2
✓ Branch 0 taken 28306 times.
✗ Branch 1 not taken.
56612 ret = dict_stats_rename_table(norm_from, norm_to, errstr, sizeof(errstr));
16694
16695
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28306 times.
56612 if (ret != DB_SUCCESS) {
16696 ib::error(ER_IB_MSG_566) << errstr;
16697
16698 push_warning(thd, Sql_condition::SL_WARNING, ER_LOCK_WAIT_TIMEOUT,
16699 errstr);
16700 }
16701 }
16702
16703 /* The duplicate key scenario was possible only for old DD since InnoDB
16704 would update it internally. With new DD, the rename conflict should be
16705 checked by server before diving into SE */
16706
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28324 times.
56648 ut_ad(error != DB_DUPLICATE_KEY);
16707
16708
1/2
✓ Branch 0 taken 28324 times.
✗ Branch 1 not taken.
56648 return (convert_error_code_to_mysql(error, 0, nullptr));
16709 56648 }
16710
16711 template int innobase_basic_ddl::rename_impl<dd::Table>(THD *, const char *,
16712 const char *,
16713 const dd::Table *,
16714 const dd::Table *,
16715 const TABLE *);
16716
16717 template int innobase_basic_ddl::rename_impl<dd::Partition>(
16718 THD *, const char *, const char *, const dd::Partition *,
16719 const dd::Partition *, const TABLE *);
16720
16721 template <typename Table>
16722 33364 innobase_truncate<Table>::~innobase_truncate() {
16723
2/2
✓ Branch 0 taken 16680 times.
✓ Branch 1 taken 2 times.
33364 if (m_table != nullptr) {
16724 33360 dd_table_close(m_table, m_thd, nullptr, false);
16725 33360 m_table = nullptr;
16726 }
16727 33364 }
16728
16729 template innobase_truncate<dd::Table>::~innobase_truncate();
16730 template innobase_truncate<dd::Partition>::~innobase_truncate();
16731
16732 template <typename Table>
16733 33396 int innobase_truncate<Table>::open_table(dict_table_t *&innodb_table) {
16734
2/2
✓ Branch 0 taken 16651 times.
✓ Branch 1 taken 47 times.
33396 if (m_dd_table->table().is_persistent()) {
16735
1/2
✓ Branch 0 taken 16651 times.
✗ Branch 1 not taken.
33302 dd::cache::Dictionary_client *client = dd::get_dd_client(m_thd);
16736
1/2
✓ Branch 0 taken 16651 times.
✗ Branch 1 not taken.
33302 dd::cache::Dictionary_client::Auto_releaser releaser(client);
16737
16738
1/2
✓ Branch 0 taken 10784 times.
✗ Branch 1 not taken.
54870 int error = dd_table_open_on_dd_obj(
16739
2/4
✓ Branch 0 taken 5867 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5867 times.
✗ Branch 3 not taken.
33302 m_thd, client, m_dd_table->table(),
16740
3/4
✓ Branch 0 taken 16651 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5867 times.
✓ Branch 3 taken 10784 times.
33302 (dd_table_is_partitioned(m_dd_table->table())
16741 ? reinterpret_cast<const dd::Partition *>(m_dd_table)
16742 : nullptr),
16743
1/2
✓ Branch 0 taken 5867 times.
✗ Branch 1 not taken.
33302 m_name, innodb_table, m_form);
16744
16745
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16651 times.
33302 if (error != 0) {
16746 return (error);
16747 }
16748
1/2
✓ Branch 0 taken 16651 times.
✗ Branch 1 not taken.
33302 } else {
16749 94 innodb_table = dd_table_open_on_name_in_mem(m_name, false);
16750
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
94 ut_ad(innodb_table->is_temporary());
16751 }
16752
16753 33396 m_table = innodb_table;
16754
16755 33396 return (0);
16756 }
16757
16758 template int innobase_truncate<dd::Table>::open_table(
16759 dict_table_t *&innodb_table);
16760 template int innobase_truncate<dd::Partition>::open_table(
16761 dict_table_t *&innodb_table);
16762
16763 template <typename Table>
16764 32530 int innobase_truncate<Table>::prepare() {
16765 32530 int error = 0;
16766
16767
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16265 times.
32530 if (m_table == nullptr) {
16768 error = open_table(m_table);
16769
16770 if (error != 0) {
16771 return (error);
16772 }
16773 }
16774
16775
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16265 times.
32530 ut_ad(m_table != nullptr);
16776
16777
1/2
✓ Branch 0 taken 16265 times.
✗ Branch 1 not taken.
32530 m_trx = check_trx_exists(m_thd);
16778
1/2
✓ Branch 0 taken 16265 times.
✗ Branch 1 not taken.
32530 m_file_per_table = dict_table_is_file_per_table(m_table);
16779 32530 m_flags = m_table->flags;
16780 32530 m_flags2 = m_table->flags2;
16781
16782
1/2
✓ Branch 0 taken 16265 times.
✗ Branch 1 not taken.
32530 update_create_info_from_table(&m_create_info, m_form);
16783
16784
1/2
✓ Branch 0 taken 16265 times.
✗ Branch 1 not taken.
32530 dd::cache::Dictionary_client *client = dd::get_dd_client(m_thd);
16785
1/2
✓ Branch 0 taken 16265 times.
✗ Branch 1 not taken.
32530 dd::cache::Dictionary_client::Auto_releaser releaser(client);
16786
16787 /* Get the autoextend_size attribute value for the table being
16788 truncated. This values will be used to create the new table as
16789 part of truncate. */
16790 32530 uint64_t autoextend_size{};
16791
16792
2/4
✓ Branch 0 taken 16265 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16265 times.
✗ Branch 3 not taken.
32530 dd::Object_id space_id = dd_first_index(m_dd_table)->tablespace_id();
16793
16794
2/2
✓ Branch 0 taken 13621 times.
✓ Branch 1 taken 2644 times.
32530 if (m_file_per_table) {
16795
1/2
✓ Branch 0 taken 13621 times.
✗ Branch 1 not taken.
27242 dd_get_tablespace_size_option(client, space_id, &autoextend_size);
16796 }
16797
16798 32530 m_create_info.m_implicit_tablespace_autoextend_size = autoextend_size;
16799
16800 32530 m_create_info.tablespace = nullptr;
16801
3/4
✓ Branch 0 taken 16265 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 47 times.
✓ Branch 3 taken 16218 times.
32530 if (m_table->is_temporary()) {
16802 94 m_create_info.options |= HA_LEX_CREATE_TMP_TABLE;
16803 } else {
16804
2/2
✓ Branch 0 taken 1555 times.
✓ Branch 1 taken 14663 times.
32436 if (m_table->tablespace != nullptr) {
16805
1/2
✓ Branch 0 taken 1555 times.
✗ Branch 1 not taken.
3110 m_create_info.tablespace = mem_strdup(m_table->tablespace);
16806 }
16807 }
16808
16809 32530 m_create_info.key_block_size = m_form->s->key_block_size;
16810
16811
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 16245 times.
32530 if (m_table->data_dir_path != nullptr) {
16812
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
40 m_create_info.data_file_name = mem_strdup(m_table->data_dir_path);
16813 } else {
16814 32490 m_create_info.data_file_name = nullptr;
16815 }
16816
16817
2/2
✓ Branch 0 taken 9653 times.
✓ Branch 1 taken 6612 times.
32530 if (m_table->can_be_evicted) {
16818
1/2
✓ Branch 0 taken 9653 times.
✗ Branch 1 not taken.
19306 dict_sys_mutex_enter();
16819
1/2
✓ Branch 0 taken 9653 times.
✗ Branch 1 not taken.
19306 dict_table_ddl_acquire(m_table);
16820
1/2
✓ Branch 0 taken 9653 times.
✗ Branch 1 not taken.
19306 dict_sys_mutex_exit();
16821 }
16822
16823
2/2
✓ Branch 0 taken 15795 times.
✓ Branch 1 taken 470 times.
32530 if (!dict_table_has_autoinc_col(m_table)) {
16824 31590 m_keep_autoinc = false;
16825 }
16826
16827 32530 return (error);
16828 32530 }
16829
16830 template <typename Table>
16831 32530 int innobase_truncate<Table>::truncate() {
16832 32530 int error = 0;
16833 32530 bool reset = false;
16834 32530 uint64_t autoinc = 0;
16835 32530 uint64_t autoinc_persisted = 0;
16836
16837 /* Rename tablespace file to avoid existing file in create. */
16838
2/2
✓ Branch 0 taken 13621 times.
✓ Branch 1 taken 2644 times.
32530 if (m_file_per_table) {
16839 27242 error = rename_tablespace();
16840 }
16841
16842
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 16260 times.
32524 DBUG_EXECUTE_IF("ib_truncate_fail_after_rename", error = HA_ERR_GENERIC;);
16843
16844
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 16259 times.
32524 if (error != 0) {
16845 6 return (error);
16846 }
16847
16848
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 16224 times.
32518 if (m_keep_autoinc) {
16849 70 autoinc_persisted = m_table->autoinc_persisted;
16850 70 autoinc = m_table->autoinc;
16851 }
16852
16853 32518 dd_table_close(m_table, m_thd, nullptr, false);
16854 32518 m_table = nullptr;
16855
16856
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 16258 times.
32518 DBUG_EXECUTE_IF("ib_truncate_crash_after_rename", DBUG_SUICIDE(););
16857
16858 32516 error = innobase_basic_ddl::delete_impl(m_thd, m_name, m_dd_table, nullptr);
16859
16860
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 16253 times.
32510 DBUG_EXECUTE_IF("ib_truncate_fail_after_delete", error = HA_ERR_GENERIC;);
16861
16862
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 16253 times.
32510 if (error != 0) {
16863 4 return (error);
16864 }
16865
16866
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 16252 times.
32506 DBUG_EXECUTE_IF("ib_truncate_crash_after_drop_old_table", DBUG_SUICIDE(););
16867
16868
2/2
✓ Branch 0 taken 16205 times.
✓ Branch 1 taken 47 times.
32504 if (m_dd_table->is_persistent()) {
16869 32410 m_dd_table->set_se_private_id(dd::INVALID_OBJECT_ID);
16870
6/10
✓ Branch 0 taken 16205 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16205 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16205 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 31520 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 31520 times.
✓ Branch 9 taken 16205 times.
127860 for (auto dd_index : *m_dd_table->indexes()) {
16871
2/4
✓ Branch 0 taken 31520 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31520 times.
✗ Branch 3 not taken.
63040 dd_index->se_private_data().clear();
16872 }
16873 }
16874
16875 32504 if (dd_table_is_partitioned(m_dd_table->table()) &&
16876
4/6
✓ Branch 0 taken 5436 times.
✓ Branch 1 taken 10816 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5436 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 16252 times.
32504 m_create_info.tablespace != nullptr &&
16877 m_dd_table->tablespace_id() == dd::INVALID_OBJECT_ID) {
16878 /* Don't change the tablespace if it's a partitioned table,
16879 so temporarily set the tablespace_id as an explicit one
16880 to make it consistent with info->tablespace */
16881 m_dd_table->set_tablespace_id(dd_first_index(m_dd_table)->tablespace_id());
16882 reset = true;
16883 }
16884
16885 32504 m_trx->in_truncate = true;
16886 32504 bool inherit_metadata = false;
16887 32504 if (dd_table_has_instant_cols(m_dd_table->table()) &&
16888
8/8
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 16197 times.
✓ Branch 2 taken 47 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 15 times.
✓ Branch 5 taken 32 times.
✓ Branch 6 taken 15 times.
✓ Branch 7 taken 16237 times.
32504 dd_table_is_partitioned(m_dd_table->table()) && !m_table_truncate) {
16889 /* For a partition table, if this is not a full table truncate, and first
16890 partition is getting truncated, make sure INSTANT metadata is inherited. */
16891 30 inherit_metadata = true;
16892 }
16893
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 16237 times.
32504 error = innobase_basic_ddl::create_impl(
16894 32504 m_thd, m_name, m_form, &m_create_info, m_dd_table, m_file_per_table,
16895 false, true, m_flags, m_flags2,
16896 30 inherit_metadata ? &m_dd_table->table() : nullptr);
16897 32492 m_trx->in_truncate = false;
16898
16899
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16246 times.
32492 if (reset) {
16900 m_dd_table->set_tablespace_id(dd::INVALID_OBJECT_ID);
16901 }
16902
16903
1/2
✓ Branch 0 taken 16246 times.
✗ Branch 1 not taken.
32492 if (error == 0) {
16904 32492 dict_sys_mutex_enter();
16905 32492 m_table = dict_table_check_if_in_cache_low(m_name);
16906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16246 times.
32492 ut_ad(m_table != nullptr);
16907 32492 m_table->acquire();
16908
16909
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 16212 times.
32492 if (m_keep_autoinc) {
16910 68 m_table->autoinc_persisted = autoinc_persisted;
16911 68 m_table->autoinc = autoinc;
16912 }
16913
16914 32492 dict_sys_mutex_exit();
16915 }
16916
16917
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 16244 times.
32492 DBUG_EXECUTE_IF("ib_truncate_fail_after_create_new_table",
16918 error = HA_ERR_GENERIC;);
16919
16920
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 16245 times.
32492 DBUG_EXECUTE_IF("ib_truncate_crash_after_create_new_table", DBUG_SUICIDE(););
16921
16922 32490 return (error);
16923 }
16924
16925 template <typename Table>
16926 27242 int innobase_truncate<Table>::rename_tablespace() {
16927
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13621 times.
27242 ut_ad(m_table != nullptr);
16928
2/4
✓ Branch 0 taken 13621 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13621 times.
27242 ut_ad(dict_table_is_file_per_table(m_table));
16929
2/4
✓ Branch 0 taken 13621 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13621 times.
27242 ut_ad(!m_table->is_temporary());
16930
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13621 times.
27242 ut_ad(m_table->trunc_name.m_name == nullptr);
16931
16932
1/2
✓ Branch 0 taken 13621 times.
✗ Branch 1 not taken.
27242 uint64_t old_size = mem_heap_get_size(m_table->heap);
16933 54484 char *temp_name = dict_mem_create_temporary_tablename(
16934
1/2
✓ Branch 0 taken 13621 times.
✗ Branch 1 not taken.
27242 m_table->heap, m_table->name.m_name, m_table->id);
16935
1/2
✓ Branch 0 taken 13621 times.
✗ Branch 1 not taken.
27242 uint64_t new_size = mem_heap_get_size(m_table->heap);
16936
16937
1/2
✓ Branch 0 taken 13621 times.
✗ Branch 1 not taken.
27242 dict_sys_mutex_enter();
16938 27242 dict_sys->size += new_size - old_size;
16939
1/2
✓ Branch 0 taken 13621 times.
✗ Branch 1 not taken.
27242 dict_sys_mutex_exit();
16940
16941 27242 std::string new_path;
16942
1/2
✓ Branch 0 taken 13621 times.
✗ Branch 1 not taken.
27242 char *old_path = fil_space_get_first_path(m_table->space);
16943
16944
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 13601 times.
27242 if (DICT_TF_HAS_DATA_DIR(m_table->flags)) {
16945
3/6
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
40 new_path = Fil_path::make_new_path(old_path, temp_name, IBD);
16946 } else {
16947
2/4
✓ Branch 0 taken 13601 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13601 times.
✗ Branch 3 not taken.
27202 char *ptr = Fil_path::make_ibd_from_table_name(temp_name);
16948
1/2
✓ Branch 0 taken 13601 times.
✗ Branch 1 not taken.
27202 new_path.assign(ptr);
16949 27202 ut::free(ptr);
16950 }
16951
16952 /* New filepath must not exist. */
16953
1/2
✓ Branch 0 taken 13621 times.
✗ Branch 1 not taken.
27242 dberr_t err = fil_rename_tablespace_check(m_table->space, old_path,
16954 new_path.c_str(), false);
16955
16956
1/2
✓ Branch 0 taken 13621 times.
✗ Branch 1 not taken.
27242 if (err == DB_SUCCESS) {
16957
1/2
✓ Branch 0 taken 13621 times.
✗ Branch 1 not taken.
27242 dict_sys_mutex_enter();
16958
1/2
✓ Branch 0 taken 13618 times.
✗ Branch 1 not taken.
27242 err = fil_rename_tablespace(m_table->space, old_path, temp_name,
16959 new_path.c_str());
16960
1/2
✓ Branch 0 taken 13618 times.
✗ Branch 1 not taken.
27236 dict_sys_mutex_exit();
16961
16962
2/2
✓ Branch 0 taken 13617 times.
✓ Branch 1 taken 1 times.
27236 if (err == DB_SUCCESS) {
16963 27234 m_table->trunc_name.m_name = temp_name;
16964 }
16965 }
16966
16967 27236 ut::free(old_path);
16968
16969
1/2
✓ Branch 0 taken 13618 times.
✗ Branch 1 not taken.
54472 return (convert_error_code_to_mysql(err, m_table->flags, nullptr));
16970 27236 }
16971
16972 template <typename Table>
16973 32500 void innobase_truncate<Table>::cleanup() {
16974
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 16248 times.
32500 if (m_table == nullptr) {
16975 4 m_table = dd_table_open_on_name_in_mem(m_name, false);
16976 }
16977
16978
2/2
✓ Branch 0 taken 16248 times.
✓ Branch 1 taken 2 times.
32500 if (m_table != nullptr) {
16979 32496 m_table->trunc_name.m_name = nullptr;
16980 }
16981
16982 32500 char *tablespace = const_cast<char *>(m_create_info.tablespace);
16983 32500 char *data_file_name = const_cast<char *>(m_create_info.data_file_name);
16984
16985 32500 ut::free(tablespace);
16986 32500 ut::free(data_file_name);
16987 32500 }
16988
16989 template <typename Table>
16990 32486 int innobase_truncate<Table>::load_fk() {
16991
5/7
✓ Branch 0 taken 5435 times.
✓ Branch 1 taken 10808 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5435 times.
✓ Branch 4 taken 10808 times.
✓ Branch 5 taken 5435 times.
✗ Branch 6 not taken.
32486 if (dd_table_is_partitioned(m_dd_table->table())) {
16992 10870 return (0);
16993 }
16994
16995 21616 int error = 0;
16996
1/2
✓ Branch 0 taken 10808 times.
✗ Branch 1 not taken.
21616 dict_names_t fk_tables;
16997
1/2
✓ Branch 0 taken 10808 times.
✗ Branch 1 not taken.
21616 dd::cache::Dictionary_client *client = dd::get_dd_client(m_thd);
16998
1/2
✓ Branch 0 taken 10808 times.
✗ Branch 1 not taken.
21616 dd::cache::Dictionary_client::Auto_releaser releaser(client);
16999
17000
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10808 times.
21616 ut_ad(m_table != nullptr);
17001 21616 error =
17002
1/2
✓ Branch 0 taken 10808 times.
✗ Branch 1 not taken.
21616 dd_table_check_for_child(client, m_table->name.m_name, nullptr, m_table,
17003 true, DICT_ERR_IGNORE_NONE, &fk_tables);
17004
17005
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10808 times.
21616 ut_ad(fk_tables.empty());
17006
17007
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10808 times.
21616 if (error != DB_SUCCESS) {
17008 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
17009 HA_ERR_CANNOT_ADD_FOREIGN,
17010 "Truncate table '%s' failed to load some"
17011 " foreign key constraints.",
17012 m_name);
17013 } else {
17014 21616 error = 0;
17015 }
17016
17017 21616 return (error);
17018 }
17019
17020 template <typename Table>
17021 32530 int innobase_truncate<Table>::exec() {
17022 32530 int error = 0;
17023
17024 32530 error = prepare();
17025
17026
1/2
✓ Branch 0 taken 16265 times.
✗ Branch 1 not taken.
32530 if (error == 0) {
17027 32530 error = truncate();
17028 }
17029
17030 32500 cleanup();
17031
17032
2/2
✓ Branch 0 taken 16243 times.
✓ Branch 1 taken 7 times.
32500 if (error == 0) {
17033 32486 error = load_fk();
17034 }
17035
17036
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 16249 times.
32500 DBUG_EXECUTE_IF("ib_truncate_crash_after_innodb_complete", DBUG_SUICIDE(););
17037
17038
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 16248 times.
32498 DBUG_EXECUTE_IF("ib_truncate_rollback_test", error = HA_ERR_GENERIC;);
17039
17040 32498 return (error);
17041 }
17042
17043 template int innobase_truncate<dd::Table>::exec();
17044 template int innobase_truncate<dd::Partition>::exec();
17045
17046 /** Check if a column is the only column in an index.
17047 @param[in] index data dictionary index
17048 @param[in] column the column to look for
17049 @return whether the column is the only column in the index */
17050 32 static bool dd_is_only_column(const dd::Index *index,
17051 const dd::Column *column) {
17052
3/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
✓ Branch 3 taken 1 times.
63 return (index->elements().size() == 1 &&
17053
6/10
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 31 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 31 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 29 times.
✓ Branch 9 taken 2 times.
63 &(*index->elements().begin())->column() == column);
17054 }
17055
17056 /** Add hidden columns and indexes to an InnoDB table definition.
17057 @param[in,out] dd_table data dictionary cache object
17058 @return error number
17059 @retval 0 on success */
17060 585282 int ha_innobase::get_extra_columns_and_keys(const HA_CREATE_INFO *,
17061 const List<Create_field> *,
17062 const KEY *, uint,
17063 dd::Table *dd_table) {
17064
1/2
✓ Branch 0 taken 585286 times.
✗ Branch 1 not taken.
585282 DBUG_TRACE;
17065
1/2
✓ Branch 0 taken 585285 times.
✗ Branch 1 not taken.
585286 THD *thd = ha_thd();
17066 585285 dd::Index *primary = nullptr;
17067 585285 bool has_fulltext = false;
17068 585285 const dd::Index *fts_doc_id_index = nullptr;
17069
17070
6/10
✓ Branch 0 taken 585284 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 585284 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 585287 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1163991 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1163988 times.
✓ Branch 9 taken 585284 times.
1749276 for (dd::Index *i : *dd_table->indexes()) {
17071 /* The name "PRIMARY" is reserved for the PRIMARY KEY */
17072
4/8
✓ Branch 0 taken 1163991 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1163990 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1163991 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1163991 times.
1163991 ut_ad((i->type() == dd::Index::IT_PRIMARY) ==
17073 !my_strcasecmp(system_charset_info, i->name().c_str(),
17074 primary_key_name));
17075
17076
4/6
✓ Branch 0 taken 1163991 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1163991 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 59 times.
✓ Branch 5 taken 1163932 times.
1163991 if (!my_strcasecmp(system_charset_info, i->name().c_str(),
17077 FTS_DOC_ID_INDEX_NAME)) {
17078
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 ut_ad(!fts_doc_id_index);
17079
2/4
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 59 times.
59 ut_ad(i->type() != dd::Index::IT_PRIMARY);
17080 59 fts_doc_id_index = i;
17081 }
17082
17083
5/8
✓ Branch 0 taken 1163990 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 605 times.
✓ Branch 5 taken 1161251 times.
✓ Branch 6 taken 2132 times.
✓ Branch 7 taken 2 times.
1163991 switch (i->algorithm()) {
17084 case dd::Index::IA_SE_SPECIFIC:
17085 ut_d(ut_error);
17086 ut_o(break);
17087 case dd::Index::IA_HASH:
17088 /* This is currently blocked
17089 by ha_innobase::is_index_algorithm_supported(). */
17090 ut_d(ut_error);
17091 ut_o(break);
17092 605 case dd::Index::IA_RTREE:
17093
2/4
✓ Branch 0 taken 605 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 605 times.
✗ Branch 3 not taken.
605 if (i->type() == dd::Index::IT_SPATIAL) {
17094 605 continue;
17095 }
17096 ut_d(ut_error);
17097 ut_o(break);
17098 1161251 case dd::Index::IA_BTREE:
17099
5/7
✓ Branch 0 taken 1161254 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 409088 times.
✓ Branch 3 taken 352527 times.
✓ Branch 4 taken 399638 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
1161251 switch (i->type()) {
17100 409088 case dd::Index::IT_PRIMARY:
17101
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 409089 times.
409088 ut_ad(!primary);
17102
4/8
✓ Branch 0 taken 409089 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 409087 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 409089 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 409089 times.
409089 ut_ad(i == *dd_table->indexes()->begin());
17103 409089 primary = i;
17104 409089 continue;
17105 352527 case dd::Index::IT_UNIQUE:
17106
7/8
✓ Branch 0 taken 37688 times.
✓ Branch 1 taken 314839 times.
✓ Branch 2 taken 37688 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 30748 times.
✓ Branch 5 taken 6940 times.
✓ Branch 6 taken 30748 times.
✓ Branch 7 taken 321779 times.
352527 if (primary == nullptr && i->is_candidate_key()) {
17107 30748 primary = i;
17108
4/8
✓ Branch 0 taken 30748 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30748 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 30748 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 30748 times.
30748 ut_ad(*dd_table->indexes()->begin() == i);
17109 }
17110 352527 continue;
17111 399638 case dd::Index::IT_MULTIPLE:
17112 399638 continue;
17113 case dd::Index::IT_FULLTEXT:
17114 case dd::Index::IT_SPATIAL:
17115 ut_d(ut_error);
17116 }
17117 1 break;
17118 2132 case dd::Index::IA_FULLTEXT:
17119
2/4
✓ Branch 0 taken 2132 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2132 times.
✗ Branch 3 not taken.
2132 if (i->type() == dd::Index::IT_FULLTEXT) {
17120 2132 has_fulltext = true;
17121 2132 continue;
17122 }
17123 ut_d(ut_error);
17124 ut_o(break);
17125 }
17126
17127
0/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3 my_error(ER_UNSUPPORTED_INDEX_ALGORITHM, MYF(0), i->name().c_str());
17128 return ER_UNSUPPORTED_INDEX_ALGORITHM;
17129 }
17130
17131
2/2
✓ Branch 0 taken 1012 times.
✓ Branch 1 taken 584272 times.
585284 if (has_fulltext) {
17132 /* Add FTS_DOC_ID_INDEX(FTS_DOC_ID) if needed */
17133 const dd::Column *fts_doc_id =
17134
1/2
✓ Branch 0 taken 1012 times.
✗ Branch 1 not taken.
1012 dd_find_column(dd_table, FTS_DOC_ID_COL_NAME);
17135
17136
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 978 times.
1012 if (fts_doc_id_index) {
17137
3/6
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
34 switch (fts_doc_id_index->type()) {
17138 case dd::Index::IT_PRIMARY:
17139 /* PRIMARY!=FTS_DOC_ID_INDEX */
17140 ut_ad(!"wrong fts_doc_id_index");
17141 [[fallthrough]];
17142 case dd::Index::IT_UNIQUE:
17143 /* We already checked for this. */
17144
2/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
32 ut_ad(fts_doc_id_index->algorithm() == dd::Index::IA_BTREE);
17145
3/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
✓ Branch 3 taken 3 times.
32 if (dd_is_only_column(fts_doc_id_index, fts_doc_id)) {
17146 29 break;
17147 }
17148 [[fallthrough]];
17149 case dd::Index::IT_MULTIPLE:
17150 case dd::Index::IT_FULLTEXT:
17151 case dd::Index::IT_SPATIAL:
17152
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 my_error(ER_INNODB_FT_WRONG_DOCID_INDEX, MYF(0),
17153
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 fts_doc_id_index->name().c_str());
17154
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 push_warning(thd, Sql_condition::SL_WARNING, ER_WRONG_NAME_FOR_INDEX,
17155 " InnoDB: Index name " FTS_DOC_ID_INDEX_NAME
17156 " is reserved"
17157 " for UNIQUE INDEX(" FTS_DOC_ID_COL_NAME
17158 ") for "
17159 " FULLTEXT Document ID indexing.");
17160 5 return ER_INNODB_FT_WRONG_DOCID_INDEX;
17161 }
17162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 ut_ad(fts_doc_id);
17163 }
17164
17165
2/2
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 922 times.
1007 if (fts_doc_id) {
17166
1/2
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
85 if (fts_doc_id->type() != dd::enum_column_types::LONGLONG ||
17167
7/8
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 73 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 67 times.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 18 times.
✓ Branch 7 taken 67 times.
152 fts_doc_id->is_nullable() ||
17168
3/6
✓ Branch 0 taken 67 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 67 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 67 times.
67 fts_doc_id->name() != FTS_DOC_ID_COL_NAME) {
17169
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 my_error(ER_INNODB_FT_WRONG_DOCID_COLUMN, MYF(0),
17170
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 fts_doc_id->name().c_str());
17171
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 push_warning(thd, Sql_condition::SL_WARNING, ER_WRONG_COLUMN_NAME,
17172 " InnoDB: Column name " FTS_DOC_ID_COL_NAME
17173 " is reserved for"
17174 " FULLTEXT Document ID indexing.");
17175 18 return ER_INNODB_FT_WRONG_DOCID_COLUMN;
17176 }
17177 } else {
17178 /* Add hidden FTS_DOC_ID column */
17179
1/2
✓ Branch 0 taken 922 times.
✗ Branch 1 not taken.
922 dd::Column *col = dd_table->add_column();
17180
1/2
✓ Branch 0 taken 922 times.
✗ Branch 1 not taken.
922 col->set_hidden(dd::Column::enum_hidden_type::HT_HIDDEN_SE);
17181
2/4
✓ Branch 0 taken 922 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 922 times.
✗ Branch 3 not taken.
922 col->set_name(FTS_DOC_ID_COL_NAME);
17182
1/2
✓ Branch 0 taken 922 times.
✗ Branch 1 not taken.
922 col->set_type(dd::enum_column_types::LONGLONG);
17183
1/2
✓ Branch 0 taken 922 times.
✗ Branch 1 not taken.
922 col->set_nullable(false);
17184
1/2
✓ Branch 0 taken 922 times.
✗ Branch 1 not taken.
922 col->set_unsigned(true);
17185
1/2
✓ Branch 0 taken 922 times.
✗ Branch 1 not taken.
922 col->set_collation_id(1);
17186 922 fts_doc_id = col;
17187 }
17188
17189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 989 times.
989 ut_ad(fts_doc_id);
17190
17191
2/2
✓ Branch 0 taken 961 times.
✓ Branch 1 taken 28 times.
989 if (fts_doc_id_index == nullptr) {
17192
2/4
✓ Branch 0 taken 961 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 961 times.
✗ Branch 3 not taken.
961 dd_set_hidden_unique_index(dd_table->add_index(), FTS_DOC_ID_INDEX_NAME,
17193 fts_doc_id);
17194 }
17195 }
17196
17197
2/2
✓ Branch 0 taken 145445 times.
✓ Branch 1 taken 439816 times.
585261 if (primary == nullptr) {
17198
1/2
✓ Branch 0 taken 145446 times.
✗ Branch 1 not taken.
145445 dd::Column *db_row_id = dd_add_hidden_column(
17199 dd_table, "DB_ROW_ID", DATA_ROW_ID_LEN, dd::enum_column_types::INT24);
17200
17201
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 145442 times.
145446 if (db_row_id == nullptr) {
17202 4 return ER_WRONG_COLUMN_NAME;
17203 }
17204
17205
2/4
✓ Branch 0 taken 145443 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 145443 times.
✗ Branch 3 not taken.
145442 primary = dd_set_hidden_unique_index(dd_table->add_first_index(),
17206 primary_key_name, db_row_id);
17207 }
17208
17209 /* Add PRIMARY KEY columns to each secondary index, including:
17210 1. all PRIMARY KEY column prefixes
17211 2. full PRIMARY KEY columns which don't exist in the secondary index */
17212
17213 std::vector<const dd::Index_element *,
17214 ut::allocator<const dd::Index_element *>>
17215
1/2
✓ Branch 0 taken 585259 times.
✗ Branch 1 not taken.
1170519 pk_elements;
17216
17217
6/10
✓ Branch 0 taken 585260 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 585259 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 585259 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1310338 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1310333 times.
✓ Branch 9 taken 585260 times.
1895597 for (dd::Index *index : *dd_table->indexes()) {
17218
2/2
✓ Branch 0 taken 585260 times.
✓ Branch 1 taken 725078 times.
1310338 if (index == primary) {
17219 585260 continue;
17220 }
17221
17222 725078 pk_elements.clear();
17223
6/10
✓ Branch 0 taken 725078 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 725078 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 725078 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 882400 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 882400 times.
✓ Branch 9 taken 725078 times.
1607478 for (const dd::Index_element *e : primary->elements()) {
17224
5/6
✓ Branch 0 taken 882400 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 855660 times.
✓ Branch 3 taken 26740 times.
✓ Branch 4 taken 756588 times.
✓ Branch 5 taken 99072 times.
1738060 if (e->is_prefix() ||
17225
1/2
✓ Branch 0 taken 855660 times.
✗ Branch 1 not taken.
855660 std::search_n(
17226
4/8
✓ Branch 0 taken 855660 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 855660 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 855660 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 855660 times.
✗ Branch 7 not taken.
855660 index->elements().begin(), index->elements().end(), 1, e,
17227 1312313 [](const dd::Index_element *ie, const dd::Index_element *e) {
17228 1312313 return (&ie->column() == &e->column());
17229
4/6
✓ Branch 0 taken 855660 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 855660 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 783328 times.
✓ Branch 5 taken 99072 times.
2593720 }) == index->elements().end()) {
17230
1/2
✓ Branch 0 taken 783328 times.
✗ Branch 1 not taken.
783328 pk_elements.push_back(e);
17231 }
17232 }
17233
17234
2/2
✓ Branch 0 taken 783328 times.
✓ Branch 1 taken 725078 times.
1508406 for (const dd::Index_element *e : pk_elements) {
17235
2/4
✓ Branch 0 taken 783328 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 783328 times.
✗ Branch 3 not taken.
783328 auto ie = index->add_element(const_cast<dd::Column *>(&e->column()));
17236
1/2
✓ Branch 0 taken 783328 times.
✗ Branch 1 not taken.
783328 ie->set_hidden(true);
17237
2/4
✓ Branch 0 taken 783328 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 783328 times.
✗ Branch 3 not taken.
783328 ie->set_order(e->order());
17238 }
17239 }
17240
17241 /* Add the InnoDB system columns DB_TRX_ID, DB_ROLL_PTR. */
17242
1/2
✓ Branch 0 taken 585256 times.
✗ Branch 1 not taken.
585260 dd::Column *db_trx_id = dd_add_hidden_column(
17243 dd_table, "DB_TRX_ID", DATA_TRX_ID_LEN, dd::enum_column_types::INT24);
17244
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 585252 times.
585256 if (db_trx_id == nullptr) {
17245 4 return ER_WRONG_COLUMN_NAME;
17246 }
17247
17248 dd::Column *db_roll_ptr =
17249
1/2
✓ Branch 0 taken 585256 times.
✗ Branch 1 not taken.
585252 dd_add_hidden_column(dd_table, "DB_ROLL_PTR", DATA_ROLL_PTR_LEN,
17250 dd::enum_column_types::LONGLONG);
17251
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 585253 times.
585256 if (db_roll_ptr == nullptr) {
17252 3 return ER_WRONG_COLUMN_NAME;
17253 }
17254
17255
1/2
✓ Branch 0 taken 585253 times.
✗ Branch 1 not taken.
585253 dd_add_hidden_element(primary, db_trx_id);
17256
1/2
✓ Branch 0 taken 585252 times.
✗ Branch 1 not taken.
585253 dd_add_hidden_element(primary, db_roll_ptr);
17257
17258 /* Add all non-virtual columns to the clustered index,
17259 unless they already part of the PRIMARY KEY. */
17260
17261 585253 for (const dd::Column *c :
17262
6/10
✓ Branch 0 taken 585252 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 585253 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 585253 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5800915 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5800914 times.
✓ Branch 9 taken 585253 times.
6971420 const_cast<const dd::Table *>(dd_table)->columns()) {
17263
8/10
✓ Branch 0 taken 5800913 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4484044 times.
✓ Branch 3 taken 1316869 times.
✓ Branch 4 taken 4484044 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8842 times.
✓ Branch 7 taken 4475202 times.
✓ Branch 8 taken 1325713 times.
✓ Branch 9 taken 4475200 times.
5800915 if (c->is_se_hidden() || c->is_virtual()) {
17264 1325713 continue;
17265 }
17266
17267
5/10
✓ Branch 0 taken 4475203 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4475201 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4475201 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4475202 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 4475201 times.
✗ Branch 9 not taken.
4475203 if (std::search_n(primary->elements().begin(), primary->elements().end(), 1,
17268 64313453 c, [](const dd::Index_element *e, const dd::Column *c) {
17269
4/4
✓ Branch 0 taken 5540617 times.
✓ Branch 1 taken 58772839 times.
✓ Branch 2 taken 719043 times.
✓ Branch 3 taken 4821573 times.
64313453 return (!e->is_prefix() && &e->column() == c);
17270
4/6
✓ Branch 0 taken 4475201 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4475203 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3756158 times.
✓ Branch 5 taken 719044 times.
8950401 }) == primary->elements().end()) {
17271
1/2
✓ Branch 0 taken 3756158 times.
✗ Branch 1 not taken.
3756158 dd_add_hidden_element(primary, c);
17272 }
17273 }
17274
17275 585253 return 0;
17276 585286 }
17277
17278 /** Set Engine specific data to dd::Table object for upgrade.
17279 @param[in,out] thd thread handle
17280 @param[in] db_name database name
17281 @param[in] table_name table name
17282 @param[in,out] dd_table data dictionary cache object
17283 @return 0 on success, non-zero on failure */
17284 3975 bool ha_innobase::upgrade_table(THD *thd, const char *db_name,
17285 const char *table_name, dd::Table *dd_table) {
17286 3975 return (dd_upgrade_table(thd, db_name, table_name, dd_table, table));
17287 }
17288
17289 /** Get storage-engine private data for a data dictionary table.
17290 @param[in,out] dd_table data dictionary table definition
17291 @param reset reset counters
17292 @retval true an error occurred
17293 @retval false success */
17294 19008 bool ha_innobase::get_se_private_data(dd::Table *dd_table, bool reset) {
17295 static uint n_tables = 0;
17296 static uint n_indexes = 0;
17297 static uint n_pages = 4;
17298
17299 /* Reset counters on second create during upgrade. */
17300
2/2
✓ Branch 0 taken 9669 times.
✓ Branch 1 taken 9339 times.
19008 if (reset) {
17301 9669 n_tables = 0;
17302 9669 n_indexes = 0;
17303 9669 n_pages = 4;
17304 // Also need to reset the set of DD table ids.
17305 9669 dict_sys_t::s_dd_table_ids.clear();
17306 }
17307 #ifdef UNIV_DEBUG
17308 19008 const uint n_indexes_old = n_indexes;
17309 #endif
17310
17311
1/2
✓ Branch 0 taken 19008 times.
✗ Branch 1 not taken.
19008 DBUG_TRACE;
17312
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19008 times.
19008 assert(dd_table != nullptr);
17313
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19008 times.
19008 assert(n_tables < innodb_dd_table_size);
17314
17315
3/6
✓ Branch 0 taken 19008 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19008 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19008 times.
✗ Branch 5 not taken.
19008 if ((*(const_cast<const dd::Table *>(dd_table))->columns().begin())
17316
3/4
✓ Branch 0 taken 19008 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5094 times.
✓ Branch 3 taken 13914 times.
19008 ->is_auto_increment()) {
17317
2/4
✓ Branch 0 taken 5094 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5094 times.
✗ Branch 3 not taken.
5094 dd_set_autoinc(dd_table->se_private_data(), 0);
17318 }
17319
17320 #ifdef UNIV_DEBUG
17321 {
17322 /* These tables must not be partitioned. */
17323
2/4
✓ Branch 0 taken 19008 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 19008 times.
19008 assert(dd_table->partitions()->empty());
17324 }
17325
17326 19008 const innodb_dd_table_t &data = innodb_dd_table[n_tables];
17327 #endif
17328
17329
2/4
✓ Branch 0 taken 19008 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 19008 times.
19008 assert(dd_table->name() == data.name);
17330
17331
1/2
✓ Branch 0 taken 19008 times.
✗ Branch 1 not taken.
19008 dd_table->set_se_private_id(++n_tables);
17332
1/2
✓ Branch 0 taken 19008 times.
✗ Branch 1 not taken.
19008 dd_table->set_tablespace_id(dict_sys_t::s_dd_dict_space_id);
17333
17334 /* Set the table id for each column to be conform with the
17335 implementation in dd_write_table(). */
17336
6/10
✓ Branch 0 taken 19008 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19008 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19008 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 154706 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 154706 times.
✓ Branch 9 taken 19008 times.
173714 for (auto dd_column : *dd_table->table().columns()) {
17337
3/6
✓ Branch 0 taken 154706 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 154706 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 154706 times.
✗ Branch 5 not taken.
154706 dd_column->se_private_data().set(dd_index_key_strings[DD_TABLE_ID],
17338 n_tables);
17339 }
17340
17341
6/10
✓ Branch 0 taken 19008 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19008 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19008 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 38252 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 38252 times.
✓ Branch 9 taken 19008 times.
57260 for (dd::Index *i : *dd_table->indexes()) {
17342
1/2
✓ Branch 0 taken 38252 times.
✗ Branch 1 not taken.
38252 i->set_tablespace_id(dict_sys_t::s_dd_dict_space_id);
17343
17344
3/4
✓ Branch 0 taken 38252 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 566 times.
✓ Branch 3 taken 37686 times.
38252 if (fsp_is_inode_page(n_pages)) {
17345 566 ++n_pages;
17346
2/4
✓ Branch 0 taken 566 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 566 times.
566 ut_ad(!fsp_is_inode_page(n_pages));
17347 }
17348
17349
1/2
✓ Branch 0 taken 38252 times.
✗ Branch 1 not taken.
38252 dd::Properties &p = i->se_private_data();
17350
17351
2/4
✓ Branch 0 taken 38252 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38252 times.
✗ Branch 3 not taken.
38252 p.set(dd_index_key_strings[DD_INDEX_ROOT], n_pages++);
17352
2/4
✓ Branch 0 taken 38252 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38252 times.
✗ Branch 3 not taken.
38252 p.set(dd_index_key_strings[DD_INDEX_ID], ++n_indexes);
17353
2/4
✓ Branch 0 taken 38252 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38252 times.
✗ Branch 3 not taken.
38252 p.set(dd_index_key_strings[DD_INDEX_TRX_ID], 0);
17354
2/4
✓ Branch 0 taken 38252 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38252 times.
✗ Branch 3 not taken.
38252 p.set(dd_index_key_strings[DD_INDEX_SPACE_ID], dict_sys_t::s_dict_space_id);
17355
2/4
✓ Branch 0 taken 38252 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38252 times.
✗ Branch 3 not taken.
38252 p.set(dd_index_key_strings[DD_TABLE_ID], n_tables);
17356 }
17357
17358
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19008 times.
19008 assert(n_indexes - n_indexes_old == data.n_indexes);
17359
17360 19008 return false;
17361 19008 }
17362
17363 /** Create an InnoDB table.
17364 @param[in] name table name in filename-safe encoding
17365 @param[in] form table structure
17366 @param[in] create_info more information on the table
17367 @param[in,out] table_def dd::Table describing table to be
17368 created. Can be adjusted by SE, the changes will be saved into data-dictionary
17369 at statement commit time.
17370 @return error number
17371 @retval 0 on success */
17372 313713 int ha_innobase::create(const char *name, TABLE *form,
17373 HA_CREATE_INFO *create_info, dd::Table *table_def) {
17374 313713 THD *thd = ha_thd();
17375
17376 313714 adjust_encryption_options(create_info, table_def);
17377
17378
2/2
✓ Branch 0 taken 10835 times.
✓ Branch 1 taken 302879 times.
313713 if (thd_sql_command(thd) == SQLCOM_TRUNCATE) {
17379 10835 return (truncate_impl(name, form, table_def));
17380 }
17381
17382 302879 trx_t *trx = check_trx_exists(thd);
17383
17384
2/2
✓ Branch 0 taken 149362 times.
✓ Branch 1 taken 153517 times.
302879 if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) {
17385 149362 innobase_register_trx(ht, thd, trx);
17386 }
17387
17388 /* Determine if this CREATE TABLE will be making a file-per-table
17389 tablespace. Note that "srv_file_per_table" is not under
17390 dict_sys mutex protection, and could be changed while creating the
17391 table. So we read the current value here and make all further
17392 decisions based on this. */
17393 302879 return (innobase_basic_ddl::create_impl(ha_thd(), name, form, create_info,
17394 table_def, srv_file_per_table, true,
17395 302863 false, 0, 0, nullptr));
17396 }
17397
17398 /** Discards or imports an InnoDB tablespace.
17399 @param[in] discard true if discard, else import
17400 @param[in,out] table_def dd::Table describing table which
17401 tablespace is to be imported or discarded. Can be adjusted by SE,
17402 the changes will be saved into the data-dictionary at statement
17403 commit time.
17404 @return 0 == success, -1 == error */
17405
17406 1458 int ha_innobase::discard_or_import_tablespace(bool discard,
17407 dd::Table *table_def) {
17408
1/2
✓ Branch 0 taken 1458 times.
✗ Branch 1 not taken.
1458 DBUG_TRACE;
17409
17410
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1458 times.
1458 ut_a(m_prebuilt->trx != nullptr);
17411
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1458 times.
1458 ut_a(m_prebuilt->trx->magic_n == TRX_MAGIC_N);
17412
3/6
✓ Branch 0 taken 1458 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1458 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1458 times.
1458 ut_a(m_prebuilt->trx == thd_to_trx(ha_thd()));
17413
17414
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1458 times.
1458 if (high_level_read_only) {
17415 return HA_ERR_TABLE_READONLY;
17416 }
17417
17418 1458 dict_table_t *dict_table = m_prebuilt->table;
17419
17420
3/4
✓ Branch 0 taken 1458 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 1445 times.
1458 if (dict_table->is_temporary()) {
17421
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR,
17422 ER_CANNOT_DISCARD_TEMPORARY_TABLE);
17423
17424 13 return HA_ERR_TABLE_NEEDS_UPGRADE;
17425 }
17426
17427
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1445 times.
1445 if (dict_table->space == TRX_SYS_SPACE) {
17428 ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR,
17429 ER_TABLE_IN_SYSTEM_TABLESPACE, dict_table->name.m_name);
17430
17431 return HA_ERR_TABLE_NEEDS_UPGRADE;
17432 }
17433
17434
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1443 times.
1445 if (DICT_TF_HAS_SHARED_SPACE(dict_table->flags)) {
17435
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 my_printf_error(ER_NOT_ALLOWED_COMMAND,
17436 "InnoDB: Cannot %s table `%s` because it is in"
17437 " a general tablespace. It must be file-per-table.",
17438 MYF(0), discard ? "discard" : "import",
17439 dict_table->name.m_name);
17440
17441 2 return HA_ERR_NOT_ALLOWED_COMMAND;
17442 }
17443
17444
1/2
✓ Branch 0 taken 1443 times.
✗ Branch 1 not taken.
1443 TrxInInnoDB trx_in_innodb(m_prebuilt->trx);
17445
17446
2/4
✓ Branch 0 taken 1443 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1443 times.
1443 if (trx_in_innodb.is_aborted()) {
17447 innobase_rollback(ht, m_user_thd, false);
17448
17449 return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd);
17450 }
17451
17452
1/2
✓ Branch 0 taken 1443 times.
✗ Branch 1 not taken.
1443 trx_start_if_not_started(m_prebuilt->trx, true, UT_LOCATION_HERE);
17453
17454 /* Obtain an exclusive lock on the table. */
17455
2/2
✓ Branch 0 taken 769 times.
✓ Branch 1 taken 674 times.
1443 dberr_t err = row_mysql_lock_table(
17456
1/2
✓ Branch 0 taken 1443 times.
✗ Branch 1 not taken.
1443 m_prebuilt->trx, dict_table, LOCK_X,
17457 discard ? "setting table lock for DISCARD TABLESPACE"
17458 : "setting table lock for IMPORT TABLESPACE");
17459
17460
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1443 times.
1443 if (err != DB_SUCCESS) {
17461 /* unable to lock the table: do nothing */
17462 /* purecov: begin inspected */
17463 return convert_error_code_to_mysql(err, dict_table->flags, nullptr);
17464 /* purecov: end */
17465 }
17466
17467 /* Concurrent clone operation is not supported. */
17468 Clone_notify notifier(Clone_notify::Type::SPACE_IMPORT,
17469
1/2
✓ Branch 0 taken 1443 times.
✗ Branch 1 not taken.
1443 dict_sys_t::s_invalid_space_id, false);
17470
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1441 times.
1443 if (notifier.failed()) {
17471 2 return notifier.get_error();
17472 }
17473
17474
2/2
✓ Branch 0 taken 768 times.
✓ Branch 1 taken 673 times.
1441 if (discard) {
17475 /* Discarding an already discarded tablespace should be an
17476 idempotent operation. Also, if the .ibd file is missing the
17477 user may want to set the DISCARD flag in order to IMPORT
17478 a new tablespace. */
17479
17480
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 750 times.
768 if (dict_table->ibd_file_missing) {
17481
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_WARN,
17482 ER_TABLESPACE_MISSING, dict_table->name.m_name);
17483 }
17484
17485 766 err = row_discard_tablespace_for_mysql(dict_table->name.m_name,
17486
1/2
✓ Branch 0 taken 766 times.
✗ Branch 1 not taken.
768 m_prebuilt->trx);
17487
17488
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 668 times.
673 } else if (!dict_table->ibd_file_missing) {
17489
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
10 ib::error(ER_IB_MSG_567)
17490
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 << "Unable to import tablespace " << dict_table->name
17491 << " because it already"
17492 " exists. Please DISCARD the tablespace"
17493
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 " before IMPORT.";
17494
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR,
17495 ER_TABLESPACE_EXISTS, dict_table->name.m_name);
17496
17497 5 return HA_ERR_TABLE_EXIST;
17498 } else {
17499
1/2
✓ Branch 0 taken 662 times.
✗ Branch 1 not taken.
668 err = row_import_for_mysql(dict_table, table_def, m_prebuilt);
17500
17501
2/2
✓ Branch 0 taken 516 times.
✓ Branch 1 taken 146 times.
662 if (err == DB_SUCCESS) {
17502
1/2
✓ Branch 0 taken 516 times.
✗ Branch 1 not taken.
516 info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE |
17503 HA_STATUS_AUTO);
17504 }
17505 }
17506
17507 /* Set the TABLESPACE DISCARD flag in the table definition
17508 on disk. */
17509
2/2
✓ Branch 0 taken 1279 times.
✓ Branch 1 taken 149 times.
1428 if (err == DB_SUCCESS) {
17510
1/2
✓ Branch 0 taken 1279 times.
✗ Branch 1 not taken.
1279 dd_table_discard_tablespace(m_prebuilt->trx->mysql_thd, dict_table,
17511 table_def, discard);
17512 }
17513
17514
6/6
✓ Branch 0 taken 1279 times.
✓ Branch 1 taken 149 times.
✓ Branch 2 taken 516 times.
✓ Branch 3 taken 763 times.
✓ Branch 4 taken 515 times.
✓ Branch 5 taken 913 times.
1944 if (err == DB_SUCCESS && !discard &&
17515
3/4
✓ Branch 0 taken 516 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 515 times.
✓ Branch 3 taken 1 times.
516 dict_stats_is_persistent_enabled(dict_table)) {
17516 dberr_t ret;
17517
17518 /* Adjust the persistent statistics. */
17519
1/2
✓ Branch 0 taken 515 times.
✗ Branch 1 not taken.
515 ret = dict_stats_update(dict_table, DICT_STATS_RECALC_PERSISTENT);
17520
17521
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 515 times.
515 if (ret != DB_SUCCESS) {
17522 push_warning_printf(ha_thd(), Sql_condition::SL_WARNING, ER_ALTER_INFO,
17523 "Error updating stats for table '%s'"
17524 " after table rebuild: %s",
17525 dict_table->name.m_name, ut_strerr(ret));
17526 }
17527 }
17528
17529
1/2
✓ Branch 0 taken 1428 times.
✗ Branch 1 not taken.
1428 return convert_error_code_to_mysql(err, dict_table->flags, nullptr);
17530 1450 }
17531
17532 10835 int ha_innobase::truncate_impl(const char *name, TABLE *form,
17533 dd::Table *table_def) {
17534
1/2
✓ Branch 0 taken 10835 times.
✗ Branch 1 not taken.
10835 DBUG_TRACE;
17535
17536 /* Truncate of intrinsic table or hard-coded DD tables is not allowed
17537 for now. */
17538
2/4
✓ Branch 0 taken 10835 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10835 times.
21670 if (table_def == nullptr ||
17539
3/6
✓ Branch 0 taken 10835 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10835 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 10835 times.
10835 dict_sys_t::is_dd_table_id(table_def->se_private_id())) {
17540 my_error(ER_NOT_ALLOWED_COMMAND, MYF(0));
17541 return HA_ERR_UNSUPPORTED;
17542 }
17543
17544
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 10831 times.
10835 if (high_level_read_only) {
17545 4 return HA_ERR_TABLE_READONLY;
17546 }
17547
17548 char norm_name[FN_REFLEN];
17549
1/2
✓ Branch 0 taken 10831 times.
✗ Branch 1 not taken.
10831 THD *thd = ha_thd();
17550 10831 dict_table_t *innodb_table = nullptr;
17551 10831 bool has_autoinc = false;
17552 10831 int error = 0;
17553
1/2
✓ Branch 0 taken 10831 times.
✗ Branch 1 not taken.
10831 const bool is_instant = dd_table_has_instant_cols(*table_def);
17554
17555
2/4
✓ Branch 0 taken 10831 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10831 times.
10831 if (!normalize_table_name(norm_name, name)) {
17556 /* purecov: begin inspected */
17557 ut_d(ut_error);
17558 ut_o(return (HA_ERR_TOO_LONG_PATH));
17559 /* purecov: end */
17560 }
17561
17562 innobase_truncate<dd::Table> truncator(thd, norm_name, form, table_def, false,
17563
1/2
✓ Branch 0 taken 10831 times.
✗ Branch 1 not taken.
10831 true);
17564
17565
1/2
✓ Branch 0 taken 10831 times.
✗ Branch 1 not taken.
10831 error = truncator.open_table(innodb_table);
17566
17567
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10831 times.
10831 if (error != 0) {
17568 return error;
17569 }
17570
17571 10831 has_autoinc = dict_table_has_autoinc_col(innodb_table);
17572
17573
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 10829 times.
10831 if (dict_table_is_discarded(innodb_table)) {
17574
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 ib_senderrf(thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_DISCARDED, norm_name);
17575 2 return HA_ERR_NO_SUCH_TABLE;
17576
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 10827 times.
10829 } else if (innodb_table->ibd_file_missing) {
17577 2 return innodb_table->keyring_encryption_info.page0_has_crypt_data == true
17578
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 ? HA_ERR_ENCRYPTION_KEY_MISSING
17579 2 : HA_ERR_TABLESPACE_MISSING;
17580 }
17581
17582
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10827 times.
10827 if (UNIV_UNLIKELY(innodb_table->is_corrupt)) return HA_ERR_CRASHED;
17583
17584
1/2
✓ Branch 0 taken 10827 times.
✗ Branch 1 not taken.
10827 trx_t *trx = check_trx_exists(thd);
17585
1/2
✓ Branch 0 taken 10827 times.
✗ Branch 1 not taken.
10827 innobase_register_trx(ht, thd, trx);
17586
17587
1/2
✓ Branch 0 taken 10811 times.
✗ Branch 1 not taken.
10827 error = truncator.exec();
17588
17589
2/2
✓ Branch 0 taken 10806 times.
✓ Branch 1 taken 5 times.
10811 if (error == 0) {
17590
2/2
✓ Branch 0 taken 380 times.
✓ Branch 1 taken 10426 times.
10806 if (has_autoinc) {
17591
2/4
✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 380 times.
✗ Branch 3 not taken.
380 dd_set_autoinc(table_def->se_private_data(), 0);
17592 }
17593
17594
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 10798 times.
10806 if (is_instant) {
17595
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
8 if (dd_clear_instant_table(*table_def, true) != DB_SUCCESS) {
17596 error = HA_ERR_GENERIC;
17597 }
17598 }
17599 }
17600
17601 10811 return error;
17602 10819 }
17603
17604 /** Drop a table.
17605 @param[in] name table name
17606 @param[in] table_def dd::Table describing table to
17607 be dropped
17608 @return error number
17609 @retval 0 on success */
17610 272273 int ha_innobase::delete_table(const char *name, const dd::Table *table_def) {
17611
4/4
✓ Branch 0 taken 161299 times.
✓ Branch 1 taken 110974 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 272268 times.
433569 if (table_def != nullptr &&
17612
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 161294 times.
161299 dict_sys_t::is_dd_table_id(table_def->se_private_id())) {
17613 2 my_error(ER_NOT_ALLOWED_COMMAND, MYF(0));
17614 2 return (HA_ERR_UNSUPPORTED);
17615 }
17616
17617 272268 THD *thd = ha_thd();
17618 272271 trx_t *trx = check_trx_exists(thd);
17619
17620
6/6
✓ Branch 0 taken 161298 times.
✓ Branch 1 taken 110974 times.
✓ Branch 2 taken 118818 times.
✓ Branch 3 taken 42477 times.
✓ Branch 4 taken 118818 times.
✓ Branch 5 taken 153451 times.
272272 if (table_def != nullptr && table_def->is_persistent()) {
17621 118818 innobase_register_trx(ht, thd, trx);
17622 }
17623
17624 272269 return (innobase_basic_ddl::delete_impl(thd, name, table_def, nullptr));
17625 }
17626
17627 /** Validate the parameters in st_alter_tablespace
17628 before using them in InnoDB tablespace functions.
17629 @param[in] type Type os tablespace being validated
17630 @param[in] alter_info How to do the command.
17631 @return MySQL handler error code like HA_... */
17632 1310 static int validate_create_tablespace_info(ib_file_suffix type,
17633 st_alter_tablespace *alter_info) {
17634 /* The parser ensures that these fields are provided. */
17635
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1310 times.
1310 ut_a(alter_info->data_file_name != nullptr);
17636
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1310 times.
1310 ut_a(alter_info->tablespace_name != nullptr);
17637
17638
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1310 times.
1310 if (high_level_read_only) {
17639 return (HA_ERR_INNODB_READ_ONLY);
17640 }
17641
17642 /* Name validation should be ensured from the SQL layer. */
17643
2/4
✓ Branch 0 taken 1310 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1310 times.
1310 ut_ad(0 == validate_tablespace_name(alter_info->ts_cmd_type,
17644 alter_info->tablespace_name));
17645
17646 1310 int error = 0;
17647
17648 /* Make sure the tablespace is not already open. */
17649
17650 space_id_t space_id;
17651
17652
1/2
✓ Branch 0 taken 1310 times.
✗ Branch 1 not taken.
1310 space_id = fil_space_get_id_by_name(alter_info->tablespace_name);
17653
17654
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1310 times.
1310 if (space_id != SPACE_UNKNOWN) {
17655 my_printf_error(ER_TABLESPACE_EXISTS,
17656 "InnoDB: A tablespace named `%s`"
17657 " already exists.",
17658 MYF(0), alter_info->tablespace_name);
17659 error = HA_ERR_TABLESPACE_EXISTS;
17660 }
17661
17662
4/4
✓ Branch 0 taken 952 times.
✓ Branch 1 taken 358 times.
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 925 times.
1310 if (type == IBD && alter_info->file_block_size) {
17663 /* Check for a bad file block size. */
17664
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 2 times.
27 if (!ut_is_2pow(alter_info->file_block_size) ||
17665
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 alter_info->file_block_size < UNIV_ZIP_SIZE_MIN ||
17666
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 alter_info->file_block_size > UNIV_PAGE_SIZE_MAX) {
17667
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
17668 "InnoDB does not support"
17669 " FILE_BLOCK_SIZE=%llu",
17670 MYF(0), alter_info->file_block_size);
17671 2 error = HA_WRONG_CREATE_OPTION;
17672
17673 /* Don't allow a file block size larger than UNIV_PAGE_SIZE. */
17674
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 21 times.
25 } else if (alter_info->file_block_size > UNIV_PAGE_SIZE) {
17675
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
17676 "InnoDB: Cannot create a tablespace"
17677 " with FILE_BLOCK_SIZE=%llu because"
17678 " INNODB_PAGE_SIZE=%lu.",
17679 MYF(0), alter_info->file_block_size, UNIV_PAGE_SIZE);
17680 4 error = HA_WRONG_CREATE_OPTION;
17681
17682 /* Don't allow a compressed tablespace when page size > 16k. */
17683
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 } else if (UNIV_PAGE_SIZE > UNIV_PAGE_SIZE_DEF &&
17684 alter_info->file_block_size != UNIV_PAGE_SIZE) {
17685 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
17686 "InnoDB: Cannot create a COMPRESSED"
17687 " tablespace when innodb_page_size >"
17688 " 16k.",
17689 MYF(0));
17690 error = HA_WRONG_CREATE_OPTION;
17691 }
17692 }
17693
17694 /* Validate AUTOEXTEND_SIZE clause. */
17695 1310 if (alter_info->autoextend_size.has_value() &&
17696
6/8
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 1267 times.
✓ Branch 2 taken 43 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 43 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 1306 times.
1353 alter_info->autoextend_size.value() > 0 &&
17697
4/6
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 39 times.
43 validate_autoextend_size_value(alter_info->autoextend_size.value()) !=
17698 DB_SUCCESS) {
17699 4 error = HA_WRONG_CREATE_OPTION;
17700 }
17701
17702 /* Validate the ADD DATAFILE name. */
17703
1/2
✓ Branch 0 taken 1310 times.
✗ Branch 1 not taken.
1310 std::string datafile_name(alter_info->data_file_name);
17704
17705 /* Undo Tablespace ADD DATAFILE filenames cannot be relative paths
17706 because it would be unclear what they are relative to. However,
17707 srv_undo_dir can be a relative directory. So evaluate this
17708 ADD DATAFILE value before it is appended to the undo dir. */
17709
7/8
✓ Branch 0 taken 358 times.
✓ Branch 1 taken 952 times.
✓ Branch 2 taken 358 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 351 times.
✓ Branch 6 taken 7 times.
✓ Branch 7 taken 1303 times.
1310 if (type == IBU && Fil_path::is_relative_path(datafile_name)) {
17710
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 my_printf_error(ER_WRONG_FILE_NAME,
17711 "The ADD DATAFILE filepath for an UNDO TABLESPACE"
17712 " cannot be a relative path.",
17713 MYF(0));
17714
17715 7 error = HA_ERR_WRONG_FILE_NAME;
17716 }
17717
17718 /* If this is an undo tablespace basename and the innodb-undo-directory
17719 is not the datadir, then use an undo::Tablespace object to get the name
17720 since it will to attach a basename to the undo directory instead of the
17721 datadir. */
17722
2/2
✓ Branch 0 taken 340 times.
✓ Branch 1 taken 18 times.
358 if (alter_info->ts_cmd_type == CREATE_UNDO_TABLESPACE &&
17723
4/4
✓ Branch 0 taken 358 times.
✓ Branch 1 taken 952 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1308 times.
1668 std::string::npos == datafile_name.find_first_of(Fil_path::SEPARATOR) &&
17724
3/4
✓ Branch 0 taken 340 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 338 times.
340 !MySQL_undo_path.is_same_as(MySQL_datadir_path)) {
17725 2 undo::Tablespace undo_space(0);
17726
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 undo_space.set_file_name(datafile_name.c_str());
17727
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 datafile_name = undo_space.file_name();
17728 2 }
17729
17730
1/2
✓ Branch 0 taken 1310 times.
✗ Branch 1 not taken.
1310 Fil_path filepath(datafile_name, true);
17731
17732 /* If this path contains a circular section such as "/anydir/../" then
17733 reject it since if that unnecessary directory reference is deleted
17734 the path will not be useaable on Linux. */
17735
3/4
✓ Branch 0 taken 1310 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 1301 times.
1310 if (filepath.is_circular()) {
17736
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 my_printf_error(ER_WRONG_FILE_NAME,
17737 "The ADD DATAFILE filepath cannot contain circular "
17738 "directory references.",
17739 MYF(0));
17740 9 error = HA_ERR_WRONG_FILE_NAME;
17741 }
17742
17743 #ifndef _WIN32
17744 /* On Non-Windows platforms, '\\' is a valid file name character.
17745 But for InnoDB datafiles, we always assume it is a directory
17746 separator and convert these to '/' */
17747
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1310 times.
1310 if (strchr(filepath, '\\') != nullptr) {
17748 ib::warn(ER_IB_MSG_568) << "Converting backslash to forward slash in"
17749 " ADD DATAFILE "
17750 << filepath.path();
17751 }
17752 #endif /* _WIN32 */
17753
17754 /* The filepath must end with a valid suffix and contain a basename of at
17755 least 1 character before the suffix. */
17756
1/2
✓ Branch 0 taken 1310 times.
✗ Branch 1 not taken.
1310 size_t dirname_len = dirname_length(filepath);
17757 1310 const char *basename = filepath + dirname_len;
17758 1310 auto basename_len = strlen(basename);
17759
17760
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1303 times.
1310 if (basename_len <= 4) {
17761
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 my_printf_error(
17762 ER_WRONG_FILE_NAME,
17763 "The ADD DATAFILE filepath does not have a proper filename.", MYF(0));
17764 7 error = HA_ERR_WRONG_FILE_NAME;
17765 }
17766
17767
4/6
✓ Branch 0 taken 1310 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1310 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 1304 times.
1310 if (!Fil_path::has_suffix(type, basename)) {
17768 6 my_printf_error(ER_WRONG_FILE_NAME,
17769 "The ADD DATAFILE filepath must end with '%s'.", MYF(0),
17770
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 dot_ext[type]);
17771 6 error = HA_ERR_WRONG_FILE_NAME;
17772 }
17773
17774
3/4
✓ Branch 0 taken 1310 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1308 times.
1310 if (!filepath.is_valid()) {
17775
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_WRONG_FILE_NAME, MYF(0), filepath.path().c_str());
17776
17777
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_printf_error(ER_WRONG_FILE_NAME, "Invalid use of ':'.", MYF(0));
17778
17779 2 return (HA_ERR_WRONG_FILE_NAME);
17780 }
17781
17782 /* If this file already exists, we cannot use this filename. */
17783
3/4
✓ Branch 0 taken 1308 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1304 times.
1308 if (os_file_exists(filepath.path().c_str())) {
17784
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_printf_error(ER_WRONG_FILE_NAME,
17785 "The ADD DATAFILE filepath already exists.", MYF(0));
17786 4 error = HA_ERR_WRONG_FILE_NAME;
17787 }
17788
17789 78 Fil_path dirpath((dirname_len == 0 ? "." : datafile_name.c_str()),
17790
5/6
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 1230 times.
✓ Branch 2 taken 78 times.
✓ Branch 3 taken 1230 times.
✓ Branch 4 taken 1308 times.
✗ Branch 5 not taken.
1386 (dirname_len == 0 ? 1 : dirname_len), true);
17791
17792
3/4
✓ Branch 0 taken 1308 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 1302 times.
1308 if (!dirpath.is_directory_and_exists()) {
17793
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 ib::error(ER_IB_MSG_WRONG_TABLESPACE_DIR, alter_info->tablespace_name);
17794
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_printf_error(ER_WRONG_FILE_NAME,
17795 "The directory does not exist or is incorrect.", MYF(0));
17796
17797 6 error = HA_ERR_WRONG_FILE_NAME;
17798 }
17799
17800 /* Do not allow the file to be created in a unique undo directory. */
17801
6/6
✓ Branch 0 taken 950 times.
✓ Branch 1 taken 358 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 944 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1307 times.
1314 if (type == IBD && MySQL_undo_path_is_unique &&
17802
3/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 1 times.
6 (MySQL_undo_path.is_same_as(dirpath) ||
17803
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 MySQL_undo_path.is_ancestor(dirpath))) {
17804
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 std::string msg("The DATAFILE location cannot be the undo directory.");
17805
17806
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_printf_error(ER_WRONG_FILE_NAME, "%s", MYF(0), msg.c_str());
17807
17808 1 ib::error(ER_IB_MSG_INVALID_LOCATION_FOR_TABLESPACE,
17809
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 alter_info->tablespace_name, msg.c_str());
17810
17811 1 error = HA_ERR_WRONG_FILE_NAME;
17812 1 }
17813
17814 /* General tablespaces can be inside but not under the datadir
17815 since those directories contain datafiles for specific schemas.*/
17816
7/8
✓ Branch 0 taken 950 times.
✓ Branch 1 taken 358 times.
✓ Branch 2 taken 950 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 943 times.
✓ Branch 6 taken 7 times.
✓ Branch 7 taken 1301 times.
1308 if (type == IBD && MySQL_datadir_path.is_ancestor(dirpath)) {
17817
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 std::string msg("The DATAFILE location cannot be under the datadir.");
17818
17819
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 my_printf_error(ER_WRONG_FILE_NAME, "%s", MYF(0), msg.c_str());
17820
17821 7 ib::error(ER_IB_MSG_INVALID_LOCATION_FOR_TABLESPACE,
17822
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 alter_info->tablespace_name, msg.c_str());
17823
17824 7 error = HA_ERR_WRONG_FILE_NAME;
17825 7 }
17826
17827 /* Validate the tablespace location. */
17828
3/4
✓ Branch 0 taken 1308 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1301 times.
✓ Branch 3 taken 7 times.
2609 bool in_datadir = MySQL_datadir_path.is_ancestor(dirpath) ||
17829
3/4
✓ Branch 0 taken 1301 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1251 times.
✓ Branch 3 taken 50 times.
1301 MySQL_datadir_path.is_same_as(dirpath);
17830 bool in_known_location =
17831
3/4
✓ Branch 0 taken 1258 times.
✓ Branch 1 taken 50 times.
✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
1308 in_datadir ? true : fil_path_is_known(dirpath.path());
17832
17833 /* All undo and general tablespaces must be in known directories */
17834
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 1288 times.
1308 if (!in_known_location) {
17835
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 std::string msg("The ");
17836
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
20 msg += (type == IBU ? "UNDO " : "");
17837
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 msg += "DATAFILE location must be in a known directory.";
17838
17839
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 my_printf_error(ER_WRONG_FILE_NAME, "%s", MYF(0), msg.c_str());
17840
17841 20 ib::error(ER_IB_MSG_INVALID_LOCATION_FOR_TABLESPACE,
17842
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 alter_info->tablespace_name, msg.c_str());
17843
17844 20 error = HA_ERR_WRONG_FILE_NAME;
17845 20 }
17846
17847 1308 return (error);
17848 1310 }
17849
17850 /** CREATE a tablespace.
17851 @param[in] hton Handlerton of InnoDB
17852 @param[in] thd Connection
17853 @param[in] alter_info How to do the command
17854 @param[in,out] dd_space Tablespace metadata
17855 @return MySQL error code*/
17856 952 static int innodb_create_tablespace(handlerton *hton, THD *thd,
17857 st_alter_tablespace *alter_info,
17858 dd::Tablespace *dd_space) {
17859 int error;
17860
1/2
✓ Branch 0 taken 952 times.
✗ Branch 1 not taken.
952 Tablespace tablespace;
17861 952 uint32_t fsp_flags = 0;
17862 952 fil_encryption_t keyring_encryption_mode{FIL_ENCRYPTION_DEFAULT};
17863
17864
1/2
✓ Branch 0 taken 952 times.
✗ Branch 1 not taken.
952 DBUG_TRACE;
17865
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 952 times.
952 assert(hton == innodb_hton_ptr);
17866
17867
2/4
✓ Branch 0 taken 952 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 952 times.
952 ut_ad(alter_info->tablespace_name == dd_space->name());
17868
2/4
✓ Branch 0 taken 952 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 952 times.
952 ut_ad(strcmp(alter_info->data_file_name,
17869 dd_tablespace_get_filename(dd_space)) == 0);
17870
17871 /* Be sure the input parameters are valid before continuing. */
17872
1/2
✓ Branch 0 taken 952 times.
✗ Branch 1 not taken.
952 error = validate_create_tablespace_info(IBD, alter_info);
17873
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 909 times.
952 if (error) {
17874 43 return error;
17875 }
17876
17877 /* Create the tablespace object. */
17878
1/2
✓ Branch 0 taken 909 times.
✗ Branch 1 not taken.
909 tablespace.set_name(alter_info->tablespace_name);
17879
17880
1/2
✓ Branch 0 taken 909 times.
✗ Branch 1 not taken.
909 dberr_t err = tablespace.add_datafile(alter_info->data_file_name);
17881
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 909 times.
909 if (err != DB_SUCCESS) {
17882 return convert_error_code_to_mysql(err, 0, nullptr);
17883 }
17884
17885
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 870 times.
948 tablespace.set_autoextend_size(alter_info->autoextend_size.has_value()
17886
1/2
✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
39 ? alter_info->autoextend_size.value()
17887 : 0);
17888
17889 /* Get the transaction associated with the current thd. */
17890
1/2
✓ Branch 0 taken 909 times.
✗ Branch 1 not taken.
909 trx_t *trx = check_trx_exists(thd);
17891
1/2
✓ Branch 0 taken 909 times.
✗ Branch 1 not taken.
909 TrxInInnoDB trx_in_innodb(trx);
17892
1/2
✓ Branch 0 taken 909 times.
✗ Branch 1 not taken.
909 trx_start_if_not_started(trx, true, UT_LOCATION_HERE);
17893 909 ++trx->will_lock;
17894
17895
1/2
✓ Branch 0 taken 909 times.
✗ Branch 1 not taken.
909 row_mysql_lock_data_dictionary(trx, UT_LOCATION_HERE);
17896
17897 /* In FSP_FLAGS, a zip_ssize of zero means that the tablespace
17898 holds non-compresssed tables. A non-zero zip_ssize means that
17899 the general tablespace can ONLY contain compressed tables. */
17900 909 uint32_t zip_size = static_cast<uint32_t>(alter_info->file_block_size);
17901
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 909 times.
909 ut_ad(zip_size <= UNIV_PAGE_SIZE_MAX);
17902
2/2
✓ Branch 0 taken 888 times.
✓ Branch 1 taken 21 times.
909 if (zip_size == 0) {
17903 888 zip_size = UNIV_PAGE_SIZE;
17904 }
17905 909 bool zipped = (zip_size != UNIV_PAGE_SIZE);
17906
1/2
✓ Branch 0 taken 909 times.
✗ Branch 1 not taken.
909 page_size_t page_size(zip_size, UNIV_PAGE_SIZE, zipped);
17907 909 bool atomic_blobs = page_size.is_compressed();
17908 909 KeyringEncryptionKeyIdInfo keyring_encryption_key_id;
17909 909 bool encrypted = false;
17910 909 dd::String_type encrypt;
17911
4/8
✓ Branch 0 taken 909 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 909 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 909 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 909 times.
✗ Branch 7 not taken.
909 if (dd_space->options().exists("encryption")) {
17912
3/6
✓ Branch 0 taken 909 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 909 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 909 times.
✗ Branch 5 not taken.
909 (void)dd_space->options().get("encryption", &encrypt);
17913
17914 /* Validate Encryption option provided */
17915
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 889 times.
909 if (Encryption::validate_for_tablespace(encrypt.c_str()) != DB_SUCCESS) {
17916 /* Incorrect encryption option */
17917
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 my_error(ER_INVALID_ENCRYPTION_OPTION, MYF(0));
17918 20 err = DB_UNSUPPORTED;
17919 22 goto error_exit;
17920 }
17921
17922 889 bool explicit_encryption{false};
17923
4/8
✓ Branch 0 taken 889 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 889 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 889 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 889 times.
✗ Branch 7 not taken.
889 if (dd_space->options().exists("explicit_encryption")) {
17924
3/6
✓ Branch 0 taken 889 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 889 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 889 times.
✗ Branch 5 not taken.
889 (void)dd_space->options().get("explicit_encryption",
17925 &explicit_encryption);
17926 }
17927 /* Validate that encryption is not MK encryption if online encryption is ON.
17928 encrypt_type is set to Y for both MK encryption and ONLINE_TO_KEYRING
17929 encryption. However, when d_t_e=ONLINE_TO_KEYRING is set it is only
17930 possible to specify MK encryption by explicitly specifying
17931 ENCRYPTION='Y'. We use this information here.
17932 */
17933
2/2
✓ Branch 0 taken 272 times.
✓ Branch 1 taken 24 times.
1185 if (Encryption::is_master_key_encryption(encrypt.c_str()) &&
17934
4/6
✓ Branch 0 taken 296 times.
✓ Branch 1 taken 593 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 272 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 889 times.
1185 explicit_encryption && Encryption::is_online_encryption_on()) {
17935 my_printf_error(
17936 ER_KEYRING_ILLEGAL_ENCRYPTION_OPTION,
17937 "InnoDB: ENCRYPTED='Y' not supported for tablespace because "
17938 "online encryption to KEYRING is turned ON.",
17939 MYF(0));
17940 err = DB_UNSUPPORTED;
17941 goto error_exit;
17942 }
17943
17944 /* If encryption is to be done */
17945
2/2
✓ Branch 0 taken 296 times.
✓ Branch 1 taken 593 times.
889 if (!Encryption::is_none(encrypt.c_str())) {
17946 /* Check if keyring is ready. */
17947
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 294 times.
296 if (!Encryption::check_keyring()) {
17948
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0));
17949 2 err = DB_UNSUPPORTED;
17950 2 goto error_exit;
17951 }
17952 294 encrypted = true;
17953 }
17954
17955
4/6
✓ Branch 0 taken 887 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 885 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
887 DBUG_EXECUTE_IF("ib_crash_during_create_tablespace_for_encryption",
17956 DBUG_SUICIDE(););
17957 }
17958
17959 /* Create the filespace flags */
17960 885 fsp_flags =
17961
1/2
✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
885 fsp_flags_init(page_size, /* page sizes and a flag if compressed */
17962 atomic_blobs, /* needed only for compressed tables */
17963 false, /* This is not a file-per-table tablespace */
17964 true, /* This is a general shared tablespace */
17965 false, /* Temporary General Tablespaces not allowed */
17966 encrypted); /* If tablespace is to be Encrypted */
17967
1/2
✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
885 tablespace.set_flags(fsp_flags);
17968
17969 1770 keyring_encryption_key_id = {
17970 885 alter_info->encryption_key_id.was_encryption_key_id_set,
17971 alter_info->encryption_key_id.id};
17972
17973 keyring_encryption_mode =
17974
1/2
✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
885 get_encryption_mode(encrypt.c_str(), alter_info->explicit_encryption);
17975
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 885 times.
885 ut_ad(keyring_encryption_mode != FIL_ENCRYPTION_ON);
17976
17977
1/2
✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
885 err = dict_build_tablespace(trx, &tablespace, keyring_encryption_mode,
17978 keyring_encryption_key_id);
17979
17980
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 882 times.
885 if (err == DB_SUCCESS) {
17981 /* Update the fil_space_t with autoextend_size value. */
17982
1/2
✓ Branch 0 taken 882 times.
✗ Branch 1 not taken.
882 fil_set_autoextend_size(tablespace.space_id(),
17983 tablespace.get_autoextend_size());
17984
17985
1/2
✓ Branch 0 taken 882 times.
✗ Branch 1 not taken.
882 err = btr_sdi_create_index(tablespace.space_id(), true);
17986
1/2
✓ Branch 0 taken 882 times.
✗ Branch 1 not taken.
882 if (err == DB_SUCCESS) {
17987 882 fsp_flags_set_sdi(fsp_flags);
17988
1/2
✓ Branch 0 taken 882 times.
✗ Branch 1 not taken.
882 tablespace.set_flags(fsp_flags);
17989
17990 /* Make sure the DD has the space_id and the flags. */
17991
1/2
✓ Branch 0 taken 882 times.
✗ Branch 1 not taken.
882 dd_write_tablespace(dd_space, tablespace.space_id(), tablespace.flags(),
17992 DD_SPACE_STATE_NORMAL);
17993 }
17994 }
17995
17996 3 error_exit:
17997
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 882 times.
907 if (err != DB_SUCCESS) {
17998
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 error = convert_error_code_to_mysql(err, 0, nullptr);
17999 }
18000
18001
1/2
✓ Branch 0 taken 907 times.
✗ Branch 1 not taken.
907 row_mysql_unlock_data_dictionary(trx);
18002
18003 907 return error;
18004 950 }
18005
18006 /** Alter AUTOEXTEND_SIZE a tablespace.
18007 @param[in] hton Handlerton of InnoDB
18008 @param[in] alter_info How to do the command
18009 @param[in] old_dd_space Tablespace metadata
18010 @return MySQL error code */
18011 5018 static int innobase_alter_autoextend_size_tablespace(
18012 handlerton *hton, st_alter_tablespace *alter_info,
18013 const dd::Tablespace *old_dd_space) {
18014 5018 space_id_t space_id = SPACE_UNKNOWN;
18015
18016
1/2
✓ Branch 0 taken 5018 times.
✗ Branch 1 not taken.
5018 DBUG_TRACE;
18017
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5018 times.
5018 assert(hton == innodb_hton_ptr);
18018
18019
3/6
✓ Branch 0 taken 5018 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5018 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5018 times.
✗ Branch 5 not taken.
5018 DEBUG_SYNC(current_thd, "innodb_alter_autoextend_size_tablespace");
18020
18021
2/4
✓ Branch 0 taken 5018 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5018 times.
5018 ut_ad(alter_info->tablespace_name == old_dd_space->name());
18022
18023
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5018 times.
5018 if (srv_read_only_mode) {
18024 return HA_ERR_INNODB_READ_ONLY;
18025 }
18026
18027 /* Validate the name */
18028
2/4
✓ Branch 0 taken 5018 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5018 times.
5018 ut_ad(0 == validate_tablespace_name(alter_info->ts_cmd_type,
18029 alter_info->tablespace_name));
18030
18031 /* Be sure that this tablespace is known and valid. */
18032
2/6
✓ Branch 0 taken 5018 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5018 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
10036 if (old_dd_space->se_private_data().get(dd_space_key_strings[DD_SPACE_ID],
18033
4/8
✓ Branch 0 taken 5018 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5018 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5018 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5018 times.
✗ Branch 7 not taken.
15054 &space_id) ||
18034
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5018 times.
5018 space_id == SPACE_UNKNOWN) {
18035 return HA_ERR_TABLESPACE_MISSING;
18036 }
18037
18038 /* Make sure tablespace is loaded. */
18039
1/2
✓ Branch 0 taken 5018 times.
✗ Branch 1 not taken.
5018 fil_space_t *space = fil_space_acquire(space_id);
18040
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5018 times.
5018 if (space == nullptr) {
18041 return HA_ERR_TABLESPACE_MISSING;
18042 }
18043
2/4
✓ Branch 0 taken 5018 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5018 times.
5018 ut_ad(fsp_flags_is_valid(space->flags));
18044
18045 /* Validate the autoextend_size value. */
18046
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5018 times.
5018 ut_ad(alter_info->autoextend_size.has_value());
18047
18048
1/2
✓ Branch 0 taken 5018 times.
✗ Branch 1 not taken.
5018 uint64_t autoextend_size = alter_info->autoextend_size.value();
18049
18050
2/2
✓ Branch 0 taken 5009 times.
✓ Branch 1 taken 9 times.
5018 if (autoextend_size > 0) {
18051
1/2
✓ Branch 0 taken 5009 times.
✗ Branch 1 not taken.
5009 int ret = validate_autoextend_size_value(autoextend_size);
18052
18053
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5007 times.
5009 if (ret != DB_SUCCESS) {
18054
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 fil_space_release(space);
18055 2 return ret;
18056 }
18057 }
18058
18059
2/4
✓ Branch 0 taken 5016 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5016 times.
✗ Branch 3 not taken.
5016 fil_set_autoextend_size(space_id, alter_info->autoextend_size.value());
18060
18061
1/2
✓ Branch 0 taken 5016 times.
✗ Branch 1 not taken.
5016 fil_space_release(space);
18062
18063 5016 return 0;
18064 5018 }
18065
18066 /**
18067 Return data filename extension for a InnoDB tablespace.
18068 */
18069
18070 134 static const char *innobase_get_tablespace_filename_ext() { return ".ibd"; }
18071
18072 /** Alter Encrypt/Unencrypt a tablespace.
18073 @param[in] hton Handlerton of InnoDB
18074 @param[in] thd Connection
18075 @param[in] alter_info How to do the command
18076 @param[in] old_dd_space Tablespace metadata
18077 @param[in,out] new_dd_space Tablespace metadata
18078 @return MySQL error code*/
18079 483 static int innobase_alter_encrypt_tablespace(handlerton *hton, THD *thd,
18080 st_alter_tablespace *alter_info,
18081 const dd::Tablespace *old_dd_space,
18082 dd::Tablespace *new_dd_space) {
18083 483 trx_t *trx = nullptr;
18084 483 dberr_t err = DB_SUCCESS;
18085 483 int error = 0;
18086 483 space_id_t space_id = SPACE_UNKNOWN;
18087
18088
1/2
✓ Branch 0 taken 483 times.
✗ Branch 1 not taken.
483 DBUG_TRACE;
18089
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 483 times.
483 assert(hton == innodb_hton_ptr);
18090
18091
4/6
✓ Branch 0 taken 457 times.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 457 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 457 times.
✗ Branch 5 not taken.
483 DEBUG_SYNC(current_thd, "innodb_alter_encrypt_tablespace");
18092
18093
2/4
✓ Branch 0 taken 483 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 483 times.
483 ut_ad(alter_info->tablespace_name == old_dd_space->name());
18094
18095
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 483 times.
483 if (srv_read_only_mode) {
18096 return HA_ERR_INNODB_READ_ONLY;
18097 }
18098
18099 /* Name validation should be ensured from the SQL layer. */
18100
2/4
✓ Branch 0 taken 483 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 483 times.
483 ut_ad(0 == validate_tablespace_name(alter_info->ts_cmd_type,
18101 alter_info->tablespace_name));
18102
18103 /* Be sure that this tablespace is known and valid. */
18104
2/6
✓ Branch 0 taken 483 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 483 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
966 if (old_dd_space->se_private_data().get(dd_space_key_strings[DD_SPACE_ID],
18105
4/8
✓ Branch 0 taken 483 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 483 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 483 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 483 times.
✗ Branch 7 not taken.
1449 &space_id) ||
18106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 483 times.
483 space_id == SPACE_UNKNOWN) {
18107 return HA_ERR_TABLESPACE_MISSING;
18108 }
18109
18110 /* Make sure keyring plugin is loaded. */
18111
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 467 times.
483 if (!Encryption::check_keyring()) {
18112
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0));
18113
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 error = convert_error_code_to_mysql(DB_ERROR, 0, nullptr);
18114 16 return error;
18115 }
18116
18117 /* Make sure tablespace is loaded. */
18118
1/2
✓ Branch 0 taken 467 times.
✗ Branch 1 not taken.
467 fil_space_t *space = fil_space_get(space_id);
18119
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 467 times.
467 if (space == nullptr) {
18120 return HA_ERR_TABLESPACE_MISSING;
18121 }
18122
2/4
✓ Branch 0 taken 467 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 467 times.
467 ut_ad(fsp_flags_is_valid(space->flags));
18123
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 467 times.
467 ut_ad(FSP_FLAGS_GET_SHARED(space->flags));
18124
18125
1/2
✓ Branch 0 taken 467 times.
✗ Branch 1 not taken.
467 const dd::Properties &oldopts = old_dd_space->options();
18126
1/2
✓ Branch 0 taken 467 times.
✗ Branch 1 not taken.
467 const dd::Properties &newopts = new_dd_space->options();
18127
18128 /* Get value of old encryption option. */
18129 467 dd::String_type oldenc;
18130
3/6
✓ Branch 0 taken 467 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 467 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 467 times.
✗ Branch 5 not taken.
467 if (oldopts.exists("encryption")) {
18131
2/4
✓ Branch 0 taken 467 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 467 times.
✗ Branch 3 not taken.
467 (void)oldopts.get("encryption", &oldenc);
18132 }
18133
18134 /* Get value of new encryption option. */
18135
3/6
✓ Branch 0 taken 467 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 467 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 467 times.
467 ut_ad(newopts.exists("encryption"));
18136 467 dd::String_type newenc;
18137
2/4
✓ Branch 0 taken 467 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 467 times.
✗ Branch 3 not taken.
467 (void)newopts.get("encryption", &newenc);
18138
18139 /* Validate new encryption option provided */
18140 467 const char *encrypt = newenc.data();
18141
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 421 times.
467 if (Encryption::validate_for_tablespace(encrypt) != DB_SUCCESS) {
18142 /* Incorrect encryption option */
18143
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 my_error(ER_INVALID_ENCRYPTION_OPTION, MYF(0));
18144
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 error = convert_error_code_to_mysql(DB_ERROR, 0, nullptr);
18145 46 return error;
18146 }
18147
18148 /* If old tablespace definition says it's encrypted */
18149 bool is_old_encrypted =
18150
3/4
✓ Branch 0 taken 421 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 208 times.
✓ Branch 3 taken 213 times.
421 !(oldenc.empty() || Encryption::is_none(oldenc.data()));
18151 /* If new tablespace definition says it's encrypted */
18152 421 bool is_new_encrypted = !Encryption::is_none(newenc.data());
18153 421 fil_space_crypt_t *crypt_data = space->crypt_data;
18154
18155 421 bool to_encrypt = false;
18156 // It is only possible to mark tablespace to be skipped by encryption threads
18157 // if it is not already encrypted.
18158
4/4
✓ Branch 0 taken 213 times.
✓ Branch 1 taken 208 times.
✓ Branch 2 taken 53 times.
✓ Branch 3 taken 160 times.
421 if (!is_old_encrypted && !is_new_encrypted &&
18159
1/2
✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
53 alter_info->explicit_encryption) {
18160
2/4
✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 53 times.
53 if (!fil_crypt_exclude_tablespace_from_rotation_permanently(space)) {
18161 return convert_error_code_to_mysql(DB_ERROR, 0, NULL);
18162 }
18163 53 return error;
18164
3/4
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 208 times.
✓ Branch 2 taken 160 times.
✗ Branch 3 not taken.
368 } else if (!is_old_encrypted && is_new_encrypted) {
18165
3/4
✓ Branch 0 taken 148 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 148 times.
✗ Branch 3 not taken.
160 DEBUG_SYNC_C("alter_encryption_to_y");
18166
2/4
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 160 times.
160 if (!fil_crypt_exclude_tablespace_from_rotation_temporarily(space)) {
18167 return convert_error_code_to_mysql(DB_ERROR, 0, NULL);
18168 }
18169
3/4
✓ Branch 0 taken 148 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 148 times.
✗ Branch 3 not taken.
160 DEBUG_SYNC_C("alter_encryption_to_y_tablespace_excluded");
18170
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 144 times.
160 if (crypt_data != nullptr) {
18171
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 mutex_enter(&crypt_data->mutex);
18172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 ut_ad(crypt_data->type == CRYPT_SCHEME_UNENCRYPTED);
18173
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 ut_ad(crypt_data->min_key_version ==
18174 ENCRYPTION_KEY_VERSION_NOT_ENCRYPTED);
18175 // setting it to default - it could have been FIL_ENCRYPTION_N
18176 // however, now that it gets encrypted with Master Key encryption
18177 // the user will have a chance to re-encrypt it with KEYRING
18178 16 crypt_data->encryption = FIL_ENCRYPTION_DEFAULT;
18179
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 mutex_exit(&space->crypt_data->mutex);
18180 }
18181 /* Encrypt tablespace */
18182 160 to_encrypt = true;
18183
3/4
✓ Branch 0 taken 208 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 145 times.
✓ Branch 3 taken 63 times.
208 } else if (is_old_encrypted && !is_new_encrypted) {
18184
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 133 times.
145 if (crypt_data) {
18185
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 mutex_enter(&crypt_data->mutex);
18186 12 bool is_keyring_encrypted{crypt_data->type != CRYPT_SCHEME_UNENCRYPTED};
18187
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 mutex_exit(&crypt_data->mutex);
18188
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (is_keyring_encrypted) {
18189 my_error(ER_EXPLICIT_DECRYPTION_OF_ONLINE_ENCRYPTED_TABLESPACE, MYF(0),
18190 space->name);
18191 return convert_error_code_to_mysql(DB_ERROR, 0, NULL);
18192 }
18193 }
18194
3/4
✓ Branch 0 taken 131 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 131 times.
✗ Branch 3 not taken.
145 DEBUG_SYNC_C("alter_encryption_to_n");
18195 // do not want master key decryption to get into way of encryption threads
18196
2/4
✓ Branch 0 taken 145 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 145 times.
145 if (!fil_crypt_exclude_tablespace_from_rotation_temporarily(space)) {
18197 return convert_error_code_to_mysql(DB_ERROR, 0, NULL);
18198 }
18199
3/4
✓ Branch 0 taken 131 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 131 times.
✗ Branch 3 not taken.
145 DEBUG_SYNC_C("alter_encryption_to_n_tablespace_excluded");
18200 /* Unencrypt tablespace */
18201 145 to_encrypt = false;
18202 145 } else {
18203 // If tablespace is encrypted by encryption threads - it cannot be
18204 // re-encrypted with Master Key encryption. It must first decrypted with
18205 // encryption threads.
18206
3/4
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 37 times.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
63 if (space->crypt_data != nullptr && alter_info->explicit_encryption) {
18207
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 mutex_enter(&crypt_data->mutex);
18208 26 bool is_keyring_encrypted{crypt_data->type != CRYPT_SCHEME_UNENCRYPTED};
18209
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 mutex_exit(&crypt_data->mutex);
18210
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (is_keyring_encrypted) {
18211 my_error(ER_ONLINE_KEYRING_TO_MK_RE_ENCRYPTION, MYF(0), space->name);
18212 return convert_error_code_to_mysql(DB_ERROR, 0, NULL);
18213 }
18214 }
18215 /* Nothing to do */
18216 63 return error;
18217 }
18218
18219 /* Get the transaction associated with the current thd */
18220
1/2
✓ Branch 0 taken 305 times.
✗ Branch 1 not taken.
305 trx = check_trx_exists(thd);
18221
1/2
✓ Branch 0 taken 305 times.
✗ Branch 1 not taken.
305 innobase_register_trx(hton, thd, trx);
18222
18223
1/2
✓ Branch 0 taken 305 times.
✗ Branch 1 not taken.
305 trx_start_if_not_started(trx, true, UT_LOCATION_HERE);
18224
18225
4/6
✓ Branch 0 taken 305 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 299 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
305 DBUG_EXECUTE_IF("alter_encrypt_tablespace_crash_before_processing",
18226 DBUG_SUICIDE(););
18227
18228 /* do encryption/unencryption processing now. */
18229
1/2
✓ Branch 0 taken 218 times.
✗ Branch 1 not taken.
299 err = fsp_alter_encrypt_tablespace(thd, space_id, to_encrypt, new_dd_space);
18230
18231
4/6
✓ Branch 0 taken 218 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 212 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
218 DBUG_EXECUTE_IF("alter_encrypt_tablespace_crash_after_processing",
18232 DBUG_SUICIDE(););
18233
18234
1/2
✓ Branch 0 taken 212 times.
✗ Branch 1 not taken.
212 error = convert_error_code_to_mysql(err, 0, nullptr);
18235 212 return error;
18236 390 }
18237
18238 /** ALTER an undo tablespace.
18239 @param[in] hton Handlerton of InnoDB
18240 @param[in] thd Connection
18241 @param[in] alter_info How to do the command
18242 @param[in] old_dd_space Tablespace metadata
18243 @param[in] new_dd_space Tablespace metadata
18244 @return MySQL error code*/
18245 5595 static int innodb_alter_tablespace(handlerton *hton, THD *thd,
18246 st_alter_tablespace *alter_info,
18247 const dd::Tablespace *old_dd_space,
18248 dd::Tablespace *new_dd_space) {
18249 5595 space_id_t space_id = SPACE_UNKNOWN;
18250 ulint old_size, new_size;
18251
18252
1/2
✓ Branch 0 taken 5595 times.
✗ Branch 1 not taken.
5595 DBUG_TRACE;
18253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5595 times.
5595 assert(hton == innodb_hton_ptr);
18254
18255
2/2
✓ Branch 0 taken 5520 times.
✓ Branch 1 taken 75 times.
5595 if (alter_info->ts_alter_tablespace_type != ALTER_TABLESPACE_RENAME &&
18256
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 5502 times.
5520 alter_info->ts_alter_tablespace_type != ALTER_TABLESPACE_OPTIONS) {
18257 18 return HA_ADMIN_NOT_IMPLEMENTED;
18258 }
18259
18260 /* Name validation should be ensured from the SQL layer. */
18261
2/4
✓ Branch 0 taken 5577 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5577 times.
5577 ut_ad(0 == validate_tablespace_name(ALTER_TABLESPACE,
18262 alter_info->tablespace_name));
18263
18264 /* Be sure that this tablespace is known and valid. */
18265
3/6
✓ Branch 0 taken 5577 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 5576 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
11154 if (old_dd_space->se_private_data().get(dd_space_key_strings[DD_SPACE_ID],
18266 5577 &space_id) ||
18267
8/14
✓ Branch 0 taken 5577 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5577 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5577 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5577 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5577 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 5576 times.
✓ Branch 12 taken 5577 times.
✗ Branch 13 not taken.
11154 space_id == SPACE_UNKNOWN || fil_space_get_size(space_id) == 0) {
18268 1 return HA_ERR_TABLESPACE_MISSING;
18269 }
18270
18271
3/4
✓ Branch 0 taken 5576 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 5575 times.
5576 if (fsp_is_undo_tablespace(space_id)) {
18272
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_printf_error(ER_WRONG_TABLESPACE_NAME,
18273 "Cannot ALTER TABLESPACE `%s` because it is an undo "
18274 "tablespace. Please use ALTER UNDO TABLESPACE.",
18275 MYF(0), alter_info->tablespace_name);
18276
18277 1 return HA_ERR_NOT_ALLOWED_COMMAND;
18278 }
18279
18280 /* ALTER_TABLESPACE_OPTIONS */
18281
2/2
✓ Branch 0 taken 5502 times.
✓ Branch 1 taken 73 times.
5575 if (alter_info->ts_alter_tablespace_type == ALTER_TABLESPACE_OPTIONS) {
18282 5502 int err = 0;
18283 /* Process the encryption option if specified with the
18284 ALTER TABLESPACE statement. */
18285
2/2
✓ Branch 0 taken 483 times.
✓ Branch 1 taken 5019 times.
5985 if (alter_info->encryption != nullptr &&
18286
8/14
✓ Branch 0 taken 483 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 483 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 483 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 483 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 483 times.
✓ Branch 9 taken 5019 times.
✓ Branch 10 taken 483 times.
✓ Branch 11 taken 5019 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
5985 new_dd_space->options().exists("encryption")) {
18287
1/2
✓ Branch 0 taken 390 times.
✗ Branch 1 not taken.
483 err = innobase_alter_encrypt_tablespace(hton, thd, alter_info,
18288 old_dd_space, new_dd_space);
18289 }
18290
18291 /* Process the AUTOEXTEND_SIZE clause if mentioned with
18292 the ALTER TABLESPACE statement. */
18293
4/4
✓ Branch 0 taken 5344 times.
✓ Branch 1 taken 65 times.
✓ Branch 2 taken 5018 times.
✓ Branch 3 taken 326 times.
10427 if (!err && alter_info->autoextend_size.has_value() &&
18294
8/14
✓ Branch 0 taken 5018 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5018 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5018 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5018 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5018 times.
✓ Branch 9 taken 391 times.
✓ Branch 10 taken 5018 times.
✓ Branch 11 taken 391 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
10427 new_dd_space->options().exists(autoextend_size_str)) {
18295
1/2
✓ Branch 0 taken 5018 times.
✗ Branch 1 not taken.
5018 err = innobase_alter_autoextend_size_tablespace(hton, alter_info,
18296 old_dd_space);
18297 }
18298
18299 /* Ignore any other ALTER TABLESPACE options. */
18300 5409 return err;
18301 }
18302
18303 /* ALTER_TABLESPACE_RENAME */
18304
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 const char *from = old_dd_space->name().c_str();
18305
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 const char *to = new_dd_space->name().c_str();
18306
18307 /* mysql tablespace can't be renamed */
18308
2/4
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 73 times.
73 if (innobase_strcasecmp(from, dict_sys_t::s_dd_space_name) == 0) {
18309 my_printf_error(ER_WRONG_TABLESPACE_NAME,
18310 "InnoDB: `mysql` is a reserved"
18311 " tablespace name.",
18312 MYF(0));
18313 return HA_WRONG_CREATE_OPTION;
18314 }
18315
18316
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
73 ut_ad(ut_strcmp(from, to) != 0);
18317
18318
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 dberr_t err = fil_rename_tablespace_by_id(space_id, from, to);
18319
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
73 if (err != DB_SUCCESS) {
18320 return convert_error_code_to_mysql(err, 0, nullptr);
18321 }
18322
18323 /* Rename any in-memory cached table->tablespace */
18324
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 dict_sys_mutex_enter();
18325
6/10
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 73 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3280 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3353 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3280 times.
✓ Branch 9 taken 73 times.
3353 for (auto table : dict_sys->table_LRU) {
18326
6/6
✓ Branch 0 taken 3003 times.
✓ Branch 1 taken 277 times.
✓ Branch 2 taken 94 times.
✓ Branch 3 taken 2909 times.
✓ Branch 4 taken 94 times.
✓ Branch 5 taken 3186 times.
3280 if (table->tablespace && strcmp(from, table->tablespace) == 0) {
18327
1/2
✓ Branch 0 taken 94 times.
✗ Branch 1 not taken.
94 old_size = mem_heap_get_size(table->heap);
18328
18329
1/2
✓ Branch 0 taken 94 times.
✗ Branch 1 not taken.
94 table->tablespace = mem_heap_strdupl(table->heap, to, strlen(to));
18330
18331
1/2
✓ Branch 0 taken 94 times.
✗ Branch 1 not taken.
94 new_size = mem_heap_get_size(table->heap);
18332 94 dict_sys->size += new_size - old_size;
18333 }
18334 }
18335
18336
6/10
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 73 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1772 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1845 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1772 times.
✓ Branch 9 taken 73 times.
1845 for (auto table : dict_sys->table_non_LRU) {
18337
4/6
✓ Branch 0 taken 1748 times.
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1748 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1772 times.
1772 if (table->tablespace && strcmp(from, table->tablespace) == 0) {
18338 old_size = mem_heap_get_size(table->heap);
18339
18340 table->tablespace = mem_heap_strdupl(table->heap, to, strlen(to));
18341
18342 new_size = mem_heap_get_size(table->heap);
18343 dict_sys->size += new_size - old_size;
18344 }
18345 }
18346
18347
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 dict_sys_mutex_exit();
18348
18349 73 return 0;
18350 5502 }
18351
18352 /** DROP a tablespace.
18353 @param[in] hton Handlerton of InnoDB
18354 @param[in] thd Connection
18355 @param[in] alter_info How to do the command
18356 @param[in] dd_space Tablespace metadata
18357 @return MySQL error code*/
18358 888 static int innodb_drop_tablespace(handlerton *hton, THD *thd,
18359 st_alter_tablespace *alter_info,
18360 const dd::Tablespace *dd_space) {
18361 888 int error = 0;
18362 888 space_id_t space_id = SPACE_UNKNOWN;
18363
18364
1/2
✓ Branch 0 taken 888 times.
✗ Branch 1 not taken.
888 DBUG_TRACE;
18365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 888 times.
888 assert(hton == innodb_hton_ptr);
18366
18367
2/4
✓ Branch 0 taken 888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 888 times.
✗ Branch 3 not taken.
888 auto dd_space_name = dd_space->name();
18368
18369
2/4
✓ Branch 0 taken 888 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 888 times.
888 ut_ad(alter_info->tablespace_name == dd_space->name());
18370
18371 /* Name validation should be ensured from the SQL layer. */
18372
2/4
✓ Branch 0 taken 888 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 888 times.
888 ut_ad(0 ==
18373 validate_tablespace_name(DROP_TABLESPACE, alter_info->tablespace_name));
18374
18375 /* Be sure that this tablespace is known and valid. */
18376
2/6
✓ Branch 0 taken 888 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 888 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1776 if (dd_space->se_private_data().get(dd_space_key_strings[DD_SPACE_ID],
18377
4/8
✓ Branch 0 taken 888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 888 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 888 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 888 times.
✗ Branch 7 not taken.
2664 &space_id) ||
18378
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 888 times.
888 space_id == SPACE_UNKNOWN) {
18379 return HA_ERR_TABLESPACE_MISSING;
18380 }
18381
18382
3/4
✓ Branch 0 taken 888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 887 times.
888 if (fsp_is_undo_tablespace(space_id)) {
18383
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_printf_error(ER_WRONG_TABLESPACE_NAME,
18384 "Cannot DROP TABLESPACE `%s` because it is an undo "
18385 "tablespace. Please use DROP UNDO TABLESPACE.",
18386 MYF(0), alter_info->tablespace_name);
18387
18388 1 return HA_ERR_NOT_ALLOWED_COMMAND;
18389 }
18390
18391
3/4
✓ Branch 0 taken 887 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 883 times.
887 if (fil_space_get_flags(space_id) == UINT32_UNDEFINED) {
18392 /* The DD knows about it but the actual tablespace is missing.
18393 Allow it to be dropped from the DD. */
18394 4 return 0;
18395 }
18396
18397 /* Get the transaction associated with the current thd. */
18398
1/2
✓ Branch 0 taken 883 times.
✗ Branch 1 not taken.
883 trx_t *trx = check_trx_exists(thd);
18399
1/2
✓ Branch 0 taken 883 times.
✗ Branch 1 not taken.
883 TrxInInnoDB trx_in_innodb(trx);
18400
1/2
✓ Branch 0 taken 883 times.
✗ Branch 1 not taken.
883 trx_start_if_not_started(trx, true, UT_LOCATION_HERE);
18401 883 ++trx->will_lock;
18402
18403 /* Acquire Exclusive MDL on SDI table of tablespace.
18404 This is to prevent concurrent purge on SDI table */
18405 883 MDL_ticket *sdi_mdl = nullptr;
18406
1/2
✓ Branch 0 taken 883 times.
✗ Branch 1 not taken.
883 dberr_t err = dd_sdi_acquire_exclusive_mdl(thd, space_id, &sdi_mdl);
18407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 883 times.
883 if (err != DB_SUCCESS) {
18408 error = convert_error_code_to_mysql(err, 0, nullptr);
18409 return error;
18410 }
18411
18412
2/4
✓ Branch 0 taken 883 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 883 times.
✗ Branch 3 not taken.
883 err = log_ddl->write_delete_space_log(trx, nullptr, space_id,
18413 dd_tablespace_get_filename(dd_space),
18414 true, false);
18415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 883 times.
883 if (err != DB_SUCCESS) {
18416 error = convert_error_code_to_mysql(err, 0, nullptr);
18417 }
18418
18419 883 return error;
18420 888 }
18421
18422 /** CREATE an undo tablespace.
18423 @param[in] hton Handlerton of InnoDB
18424 @param[in] thd Connection
18425 @param[in] alter_info How to do the command
18426 @param[in,out] dd_space Tablespace metadata
18427 @return MySQL error code*/
18428 358 static int innodb_create_undo_tablespace(handlerton *hton, THD *thd,
18429 st_alter_tablespace *alter_info,
18430 dd::Tablespace *dd_space) {
18431 358 int error = 0;
18432 dberr_t err;
18433 uint32_t flags;
18434
18435
1/2
✓ Branch 0 taken 358 times.
✗ Branch 1 not taken.
358 DBUG_TRACE;
18436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 358 times.
358 assert(hton == innodb_hton_ptr);
18437
18438
2/4
✓ Branch 0 taken 358 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 358 times.
358 ut_ad(alter_info->tablespace_name == dd_space->name());
18439
2/4
✓ Branch 0 taken 358 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 358 times.
358 ut_ad(strcmp(alter_info->data_file_name,
18440 dd_tablespace_get_filename(dd_space)) == 0);
18441
18442 /* Be sure the input parameters are valid before continuing. */
18443
1/2
✓ Branch 0 taken 358 times.
✗ Branch 1 not taken.
358 error = validate_create_tablespace_info(IBU, alter_info);
18444
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 343 times.
358 if (error) {
18445 15 return error;
18446 }
18447
18448 /* Notify clone about the UNDO DDL and possibly wait. We don't
18449 need similar notification for drop which is recoverable with DDL
18450 log. */
18451 Clone_notify notifier(Clone_notify::Type::SPACE_UNDO_DDL,
18452
1/2
✓ Branch 0 taken 343 times.
✗ Branch 1 not taken.
343 dict_sys_t::s_invalid_space_id, false);
18453
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 342 times.
343 if (notifier.failed()) {
18454 1 return notifier.get_error();
18455 }
18456
18457 /* Create the tablespace object. */
18458
18459 /* Serialize all undo tablespace DDLs */
18460
1/2
✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
342 mutex_enter(&undo::ddl_mutex);
18461
18462 /* Get the transaction associated with the current thd and make
18463 sure it will not block this DDL. */
18464
1/2
✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
342 check_trx_exists(thd);
18465
18466 /* Allocate a new transaction for this DDL */
18467
1/2
✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
342 trx_t *trx = innobase_trx_allocate(thd);
18468
1/2
✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
342 trx_start_if_not_started(trx, true, UT_LOCATION_HERE);
18469 342 ++trx->will_lock;
18470
18471 /* Find the next available undo space number and mark it in-use. */
18472
1/2
✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
342 space_id_t space_id = undo::get_next_available_space_num();
18473
5/6
✓ Branch 0 taken 341 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 341 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 341 times.
683 if (space_id == SPACE_UNKNOWN ||
18474 341 undo::spaces->size() == FSP_MAX_UNDO_TABLESPACES) {
18475 /* All available explicit undo tablespaces have been used. */
18476 1 ib::error(ER_IB_MSG_MAX_UNDO_SPACES_REACHED, alter_info->tablespace_name,
18477
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 alter_info->data_file_name, int{FSP_MAX_UNDO_TABLESPACES});
18478 1 error = HA_ERR_TABLESPACE_EXISTS;
18479
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 trx_rollback_for_mysql(trx);
18480 1 goto cleanup;
18481 }
18482
18483
1/2
✓ Branch 0 taken 341 times.
✗ Branch 1 not taken.
341 err = srv_undo_tablespace_create(alter_info->tablespace_name,
18484 alter_info->data_file_name, space_id);
18485
18486
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 339 times.
341 if (err != DB_SUCCESS) {
18487
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 error = convert_error_code_to_mysql(err, 0, nullptr);
18488
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 trx_rollback_for_mysql(trx);
18489 2 goto cleanup;
18490 }
18491
18492
1/2
✓ Branch 0 taken 339 times.
✗ Branch 1 not taken.
339 innobase_commit_low(trx);
18493
18494 /* Make sure the DD has the space_id and the flags. */
18495
1/2
✓ Branch 0 taken 339 times.
✗ Branch 1 not taken.
339 flags = fsp_flags_init(univ_page_size, false, false, false, false);
18496
1/2
✓ Branch 0 taken 339 times.
✗ Branch 1 not taken.
339 dd_write_tablespace(dd_space, space_id, flags, DD_SPACE_STATE_ACTIVE);
18497
18498 /* Mark the undo tablespace 'active' in undo::spaces. */
18499
1/2
✓ Branch 0 taken 339 times.
✗ Branch 1 not taken.
339 undo::set_active(space_id);
18500
1/2
✓ Branch 0 taken 339 times.
✗ Branch 1 not taken.
339 ut_d(ib::info(ER_IB_MSG_UNDO_MARKED_ACTIVE, alter_info->tablespace_name));
18501
18502 342 cleanup:
18503
1/2
✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
342 trx_free_for_mysql(trx);
18504
18505
1/2
✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
342 mutex_exit(&undo::ddl_mutex);
18506
18507
1/2
✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
342 ib::info(ER_IB_MSG_CREATED_UNDO_SPACE, alter_info->tablespace_name);
18508
18509 342 return error;
18510 358 }
18511
18512 /** ALTER an undo tablespace to ACTIVE.
18513 @param[in] undo_space Undo Tablespace object
18514 @param[in] dd_state Current state in the DD.
18515 @param[in] dd_space Tablespace metadata
18516 @return MySQL error code*/
18517 213 static int innodb_alter_undo_tablespace_active(undo::Tablespace *undo_space,
18518 dd::String_type dd_state,
18519 dd::Tablespace *dd_space) {
18520 /* Change the state of the undo tablespace.
18521 ALTER UNDO TABLESPACE is idempotent. */
18522
2/2
✓ Branch 0 taken 209 times.
✓ Branch 1 taken 4 times.
213 if (dd_state != dd_space_state_values[DD_SPACE_STATE_ACTIVE]) {
18523 209 dd_tablespace_set_state(dd_space, DD_SPACE_STATE_ACTIVE);
18524 }
18525
18526 /* Start using this undo tablespace. */
18527 213 undo_space->alter_active();
18528
18529 213 return (0);
18530 }
18531
18532 /** ALTER an undo tablespace to INACTIVE.
18533 @param[in] undo_space Undo Tablespace object
18534 @param[in] dd_state Current state in the DD.
18535 @param[in] dd_space Tablespace metadata
18536 @return MySQL error code*/
18537 553 static int innodb_alter_undo_tablespace_inactive(undo::Tablespace *undo_space,
18538 dd::String_type dd_state,
18539 dd::Tablespace *dd_space) {
18540 /* If it is already empty, just return. */
18541
5/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 552 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 552 times.
554 if (undo_space->is_empty() &&
18542 1 dd_state == dd_space_state_values[DD_SPACE_STATE_EMPTY]) {
18543 1 return (0);
18544 }
18545
18546
2/2
✓ Branch 0 taken 531 times.
✓ Branch 1 taken 21 times.
552 if (undo_space->is_active()) {
18547 /* There must be at least 2 active undo tablespaces besides the one we
18548 are trying to make inactive explicitly. One of those two could be in
18549 the process of being implicitly truncated. So if one other space is
18550 inactive_implicit, then it is being truncated and will be put back
18551 to active before this undo_space is truncated. */
18552 531 ulint other_active_spaces = 0;
18553
2/2
✓ Branch 0 taken 18702 times.
✓ Branch 1 taken 531 times.
19233 for (auto undo_ts : undo::spaces->m_spaces) {
18554
2/2
✓ Branch 0 taken 18171 times.
✓ Branch 1 taken 531 times.
18702 if (undo_ts != undo_space) {
18555
3/4
✓ Branch 0 taken 18171 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9590 times.
✓ Branch 3 taken 8581 times.
18171 if (undo_ts->is_active()) {
18556 9590 other_active_spaces++;
18557
5/6
✓ Branch 0 taken 8581 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 8556 times.
✓ Branch 4 taken 25 times.
✓ Branch 5 taken 8556 times.
8606 } else if (undo_ts->is_inactive_implicit() &&
18558 25 purge_sys->undo_trunc.get_marked_space_num() ==
18559
2/4
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
25 undo_ts->num()) {
18560 25 other_active_spaces++;
18561 }
18562 }
18563 }
18564
18565
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 517 times.
531 if (other_active_spaces < 2) {
18566 14 my_printf_error(ER_DISALLOWED_OPERATION,
18567 "Cannot set %s inactive since there would be"
18568 " less than 2 undo tablespaces left active.",
18569 MYF(0), undo_space->space_name());
18570
18571 14 return (HA_ERR_NOT_ALLOWED_COMMAND);
18572 }
18573 }
18574
18575 /* If truncation is happening too often on this undo tablespace there
18576 may be too many old files still in the fil_system with their pages
18577 still in the buffer pool. If this is the case, return an error. */
18578 538 auto count = fil_count_undo_deleted(undo_space->num());
18579
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 538 times.
538 if (count > CONCURRENT_UNDO_TRUNCATE_LIMIT) {
18580 my_printf_error(ER_DISALLOWED_OPERATION,
18581 "Cannot set %s inactive since there would be more"
18582 " than %zu old versions of this undo tablespace"
18583 " in cache. Please wait for the next checkpoint.",
18584 MYF(0), undo_space->space_name(),
18585 CONCURRENT_UNDO_TRUNCATE_LIMIT);
18586
18587 return (HA_ERR_NOT_ALLOWED_COMMAND);
18588 }
18589
18590 /* Make sure the DD shows inactive if it is active. */
18591 538 dd_tablespace_set_state(dd_space, DD_SPACE_STATE_INACTIVE);
18592
18593 /* Apply this to new transactions. */
18594 538 undo_space->set_inactive_explicit();
18595
1/2
✓ Branch 0 taken 538 times.
✗ Branch 1 not taken.
538 ut_d(ib::info(ER_IB_MSG_UNDO_ALTERED_INACTIVE, undo_space->file_name()));
18596
18597 538 srv_wake_purge_thread_if_not_active();
18598
18599 538 return (0);
18600 }
18601
18602 /** ALTER an undo tablespace. Either make it ACTIVE or INACTIVE.
18603 @param[in] hton Handlerton of InnoDB
18604 @param[in] alter_info How to do the command
18605 @param[in] dd_space Tablespace metadata
18606 @return MySQL error code*/
18607 768 static int innodb_alter_undo_tablespace(handlerton *hton,
18608 st_alter_tablespace *alter_info,
18609 dd::Tablespace *dd_space) {
18610 768 space_id_t space_id = SPACE_UNKNOWN;
18611
18612
1/2
✓ Branch 0 taken 768 times.
✗ Branch 1 not taken.
768 DBUG_TRACE;
18613
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 768 times.
768 assert(hton == innodb_hton_ptr);
18614
18615
2/4
✓ Branch 0 taken 768 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 768 times.
768 ut_ad(alter_info->tablespace_name == dd_space->name());
18616
18617 /* Name validation should be ensured from the SQL layer. */
18618
2/4
✓ Branch 0 taken 768 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 768 times.
768 ut_ad(0 == validate_tablespace_name(ALTER_UNDO_TABLESPACE,
18619 alter_info->tablespace_name));
18620
18621 /* Be sure that this tablespace is known and valid. */
18622
2/6
✓ Branch 0 taken 768 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 768 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1536 if (dd_space->se_private_data().get(dd_space_key_strings[DD_SPACE_ID],
18623 768 &space_id) ||
18624
7/14
✓ Branch 0 taken 768 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 768 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 768 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 768 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 768 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 768 times.
✓ Branch 12 taken 768 times.
✗ Branch 13 not taken.
1536 space_id == SPACE_UNKNOWN || fil_space_get_size(space_id) == 0) {
18625 return HA_ERR_TABLESPACE_MISSING;
18626 }
18627
18628
3/4
✓ Branch 0 taken 768 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 766 times.
768 if (!fsp_is_undo_tablespace(space_id)) {
18629
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_printf_error(ER_WRONG_TABLESPACE_NAME,
18630 "Cannot ALTER UNDO TABLESPACE `%s` because it is a "
18631 "general tablespace. Please use ALTER TABLESPACE.",
18632 MYF(0), alter_info->tablespace_name);
18633
18634 2 return HA_ERR_NOT_ALLOWED_COMMAND;
18635 }
18636
18637 /* Get the current state of the undo tablespace from the DD. */
18638 766 dd::String_type dd_state;
18639
1/2
✓ Branch 0 taken 766 times.
✗ Branch 1 not taken.
766 dd_tablespace_get_state(dd_space, &dd_state, space_id);
18640
18641 /* Serialize all undo tablespace DDLs */
18642
1/2
✓ Branch 0 taken 766 times.
✗ Branch 1 not taken.
766 mutex_enter(&undo::ddl_mutex);
18643
18644 /* Get the current undo_space object. */
18645
1/2
✓ Branch 0 taken 766 times.
✗ Branch 1 not taken.
766 undo::spaces->s_lock();
18646 766 space_id_t space_num = undo::id2num(space_id);
18647
1/2
✓ Branch 0 taken 766 times.
✗ Branch 1 not taken.
766 undo::Tablespace *undo_space = undo::spaces->find(space_num);
18648
18649 /* ALTER UNDO TABLESPACE is idempotent. */
18650 766 int err = 0;
18651
2/3
✓ Branch 0 taken 213 times.
✓ Branch 1 taken 553 times.
✗ Branch 2 not taken.
766 switch (alter_info->ts_alter_tablespace_type) {
18652 213 case ALTER_UNDO_TABLESPACE_SET_ACTIVE:
18653
2/4
✓ Branch 0 taken 213 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 213 times.
✗ Branch 3 not taken.
213 err = innodb_alter_undo_tablespace_active(undo_space, dd_state, dd_space);
18654 213 break;
18655
18656 553 case ALTER_UNDO_TABLESPACE_SET_INACTIVE:
18657 err =
18658
2/4
✓ Branch 0 taken 553 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 553 times.
✗ Branch 3 not taken.
553 innodb_alter_undo_tablespace_inactive(undo_space, dd_state, dd_space);
18659 553 break;
18660
18661 default:
18662 err = HA_ADMIN_NOT_IMPLEMENTED;
18663 }
18664
18665
1/2
✓ Branch 0 taken 766 times.
✗ Branch 1 not taken.
766 undo::spaces->s_unlock();
18666
18667
1/2
✓ Branch 0 taken 766 times.
✗ Branch 1 not taken.
766 mutex_exit(&undo::ddl_mutex);
18668
18669 766 return err;
18670 768 }
18671
18672 /** DROP an undo tablespace.
18673 @param[in] hton Handlerton of InnoDB
18674 @param[in] thd Connection
18675 @param[in] alter_info How to do the command
18676 @param[in] dd_space Tablespace metadata
18677 @return MySQL error code*/
18678 330 static int innodb_drop_undo_tablespace(handlerton *hton, THD *thd,
18679 st_alter_tablespace *alter_info,
18680 const dd::Tablespace *dd_space) {
18681 330 space_id_t space_id = SPACE_UNKNOWN;
18682
18683
1/2
✓ Branch 0 taken 330 times.
✗ Branch 1 not taken.
330 DBUG_TRACE;
18684
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 330 times.
330 assert(hton == innodb_hton_ptr);
18685
18686
2/4
✓ Branch 0 taken 330 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 330 times.
330 ut_ad(alter_info->tablespace_name == dd_space->name());
18687
18688 /* Name validation should be ensured from the SQL layer. */
18689
2/4
✓ Branch 0 taken 330 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 330 times.
330 ut_ad(0 == validate_tablespace_name(DROP_UNDO_TABLESPACE,
18690 alter_info->tablespace_name));
18691
18692 /* Be sure that this tablespace is known and valid. */
18693
2/6
✓ Branch 0 taken 330 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 330 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
660 if (dd_space->se_private_data().get(dd_space_key_strings[DD_SPACE_ID],
18694
4/8
✓ Branch 0 taken 330 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 330 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 330 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 330 times.
✗ Branch 7 not taken.
990 &space_id) ||
18695
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 330 times.
330 space_id == SPACE_UNKNOWN) {
18696 return HA_ERR_TABLESPACE_MISSING;
18697 }
18698
18699
3/4
✓ Branch 0 taken 330 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 329 times.
330 if (!fsp_is_undo_tablespace(space_id)) {
18700
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_printf_error(ER_WRONG_TABLESPACE_NAME,
18701 "Cannot DROP UNDO TABLESPACE `%s` because it is a "
18702 "general tablespace. Please use DROP TABLESPACE.",
18703 MYF(0), alter_info->tablespace_name);
18704
18705 1 return HA_ERR_NOT_ALLOWED_COMMAND;
18706 }
18707
18708 /* Serialize all undo tablespace DDLs */
18709
1/2
✓ Branch 0 taken 329 times.
✗ Branch 1 not taken.
329 mutex_enter(&undo::ddl_mutex);
18710
18711
1/2
✓ Branch 0 taken 329 times.
✗ Branch 1 not taken.
329 undo::spaces->x_lock();
18712 329 space_id_t space_num = undo::id2num(space_id);
18713
1/2
✓ Branch 0 taken 329 times.
✗ Branch 1 not taken.
329 undo::Tablespace *undo_space = undo::spaces->find(space_num);
18714
18715 /* If the undo space is missing, allow the DROP UNDO TABLESPACE to
18716 continue to completion. */
18717
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 327 times.
329 if (undo_space == nullptr) {
18718
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 undo::spaces->x_unlock();
18719
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 mutex_exit(&undo::ddl_mutex);
18720
18721 /* Start the transaction associated with the current thd so that MySQL
18722 can continue. */
18723
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 trx_t *trx = check_trx_exists(thd);
18724
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 trx_start_if_not_started(trx, true, UT_LOCATION_HERE);
18725 2 ++trx->will_lock;
18726
18727 2 return (0);
18728 }
18729
18730 /* Verify that the undo tablespace is not one of the first two undo spaces,
18731 has been altered inactive and is now empty. */
18732
4/6
✓ Branch 0 taken 327 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 327 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 323 times.
654 if (undo_space->num() <= FSP_IMPLICIT_UNDO_TABLESPACES ||
18733
3/4
✓ Branch 0 taken 327 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 323 times.
327 !undo_space->is_empty()) {
18734
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 ib::error err_msg;
18735
3/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 err_msg << "Cannot drop undo tablespace '" << undo_space->space_name();
18736
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if (undo_space->num() <= FSP_IMPLICIT_UNDO_TABLESPACES) {
18737 err_msg << "' because it was not created explicitly.";
18738
3/10
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
4 } else if (undo_space->is_active() || undo_space->is_inactive_implicit()) {
18739
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 err_msg << "' because it is active. "
18740
3/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
8 << "Please do: ALTER UNDO TABLESPACE " << undo_space->space_name()
18741
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 << " SET INACTIVE;";
18742 } else {
18743 err_msg << "' because it is still being truncated."
18744 " Please try again later.";
18745 }
18746
18747
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 undo::spaces->x_unlock();
18748
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 mutex_exit(&undo::ddl_mutex);
18749
18750 4 return HA_ERR_TABLESPACE_IS_NOT_EMPTY;
18751 4 }
18752
18753 /* We don't need to invalidate buffer pool pages belonging to this undo
18754 tablespace before dropping it, as they will be set as stale and to be
18755 lazily freed. */
18756
18757 /* Save the file name before undo_space is dropped. */
18758
2/4
✓ Branch 0 taken 323 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 323 times.
✗ Branch 3 not taken.
323 std::string file_name{undo_space->file_name()};
18759
18760 /* Empty and inactive, take it out of view. */
18761
1/2
✓ Branch 0 taken 323 times.
✗ Branch 1 not taken.
323 undo::spaces->drop(undo_space);
18762
1/2
✓ Branch 0 taken 323 times.
✗ Branch 1 not taken.
323 undo::spaces->x_unlock();
18763
18764 /* Get the transaction associated with the current thd and write a
18765 delete_space record to the DDL_LOG. */
18766
1/2
✓ Branch 0 taken 323 times.
✗ Branch 1 not taken.
323 trx_t *trx = check_trx_exists(thd);
18767
1/2
✓ Branch 0 taken 323 times.
✗ Branch 1 not taken.
323 TrxInInnoDB trx_in_innodb(trx);
18768
1/2
✓ Branch 0 taken 323 times.
✗ Branch 1 not taken.
323 trx_start_if_not_started(trx, true, UT_LOCATION_HERE);
18769 323 ++trx->will_lock;
18770
18771
1/2
✓ Branch 0 taken 323 times.
✗ Branch 1 not taken.
323 auto err = log_ddl->write_delete_space_log(trx, nullptr, space_id,
18772 file_name.c_str(), true, false);
18773 323 int error = 0;
18774
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 323 times.
323 if (err != DB_SUCCESS) {
18775 error = convert_error_code_to_mysql(err, 0, nullptr);
18776 }
18777
18778
1/2
✓ Branch 0 taken 323 times.
✗ Branch 1 not taken.
323 mutex_exit(&undo::ddl_mutex);
18779
18780
1/2
✓ Branch 0 taken 323 times.
✗ Branch 1 not taken.
323 ib::info(ER_IB_MSG_DROPPED_UNDO_SPACE, alter_info->tablespace_name);
18781
18782 323 return error;
18783 330 }
18784
18785 /** This API handles CREATE, ALTER & DROP commands for InnoDB tablespaces.
18786 @param[in] hton Handlerton of InnoDB
18787 @param[in] thd Connection
18788 @param[in] alter_info Describes the command and how to do it.
18789 @param[in] old_ts_def Old version of dd::Tablespace object for the
18790 tablespace.
18791 @param[in,out] new_ts_def New version of dd::Tablespace object for the
18792 tablespace. Can be adjusted by SE. Changes will be persisted in the
18793 data-dictionary at statement commit.
18794 @return MySQL error code*/
18795 8896 static int innobase_alter_tablespace(handlerton *hton, THD *thd,
18796 st_alter_tablespace *alter_info,
18797 const dd::Tablespace *old_ts_def,
18798 dd::Tablespace *new_ts_def) {
18799 8896 int error = 0; /* return zero for success */
18800
1/2
✓ Branch 0 taken 8896 times.
✗ Branch 1 not taken.
8896 DBUG_TRACE;
18801
18802
4/4
✓ Branch 0 taken 8895 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 8894 times.
8896 if (srv_read_only_mode || srv_force_recovery > 0) {
18803
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 my_printf_error(ER_INNODB_READ_ONLY,
18804 "Changes to undo tablespaces are not allowed in"
18805 " %s mode",
18806 MYF(0),
18807 (srv_read_only_mode ? "read_only" : "force_recovery"));
18808 2 error = HA_ERR_INNODB_READ_ONLY;
18809 2 goto handle_error;
18810 }
18811
18812
7/7
✓ Branch 0 taken 952 times.
✓ Branch 1 taken 5595 times.
✓ Branch 2 taken 888 times.
✓ Branch 3 taken 358 times.
✓ Branch 4 taken 768 times.
✓ Branch 5 taken 330 times.
✓ Branch 6 taken 3 times.
8894 switch (alter_info->ts_cmd_type) {
18813 952 case CREATE_TABLESPACE:
18814
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 952 times.
952 ut_ad(new_ts_def != nullptr);
18815
1/2
✓ Branch 0 taken 950 times.
✗ Branch 1 not taken.
952 error = innodb_create_tablespace(hton, thd, alter_info, new_ts_def);
18816 950 break;
18817
18818 5595 case ALTER_TABLESPACE:
18819
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5595 times.
5595 ut_ad(old_ts_def != nullptr);
18820
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5595 times.
5595 ut_ad(new_ts_def != nullptr);
18821
1/2
✓ Branch 0 taken 5502 times.
✗ Branch 1 not taken.
5595 error = innodb_alter_tablespace(hton, thd, alter_info, old_ts_def,
18822 new_ts_def);
18823 5502 break;
18824
18825 888 case DROP_TABLESPACE:
18826
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 888 times.
888 ut_ad(old_ts_def != nullptr);
18827
1/2
✓ Branch 0 taken 888 times.
✗ Branch 1 not taken.
888 error = innodb_drop_tablespace(hton, thd, alter_info, old_ts_def);
18828 888 break;
18829
18830 358 case CREATE_UNDO_TABLESPACE:
18831
1/2
✓ Branch 0 taken 358 times.
✗ Branch 1 not taken.
358 error = innodb_create_undo_tablespace(hton, thd, alter_info, new_ts_def);
18832 358 break;
18833
18834 768 case ALTER_UNDO_TABLESPACE:
18835
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 768 times.
768 ut_ad(new_ts_def != nullptr);
18836
1/2
✓ Branch 0 taken 768 times.
✗ Branch 1 not taken.
768 error = innodb_alter_undo_tablespace(hton, alter_info, new_ts_def);
18837 768 break;
18838
18839 330 case DROP_UNDO_TABLESPACE:
18840
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 330 times.
330 ut_ad(old_ts_def != nullptr);
18841
1/2
✓ Branch 0 taken 330 times.
✗ Branch 1 not taken.
330 error = innodb_drop_undo_tablespace(hton, thd, alter_info, old_ts_def);
18842 330 break;
18843
18844 3 default:
18845 3 error = HA_ADMIN_NOT_IMPLEMENTED;
18846 }
18847
18848 8801 handle_error:
18849
2/2
✓ Branch 0 taken 201 times.
✓ Branch 1 taken 8600 times.
8801 if (error) {
18850 /* These are the most common message params */
18851 201 const char *ibd_type = "TABLESPACE";
18852 201 const char *undo_type = "UNDO TABLESPACE";
18853 201 uint32_t code = ER_CREATE_FILEGROUP_FAILED;
18854 201 const char *subject = ibd_type;
18855
18856 /* Modify those params as needed. */
18857
7/11
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 87 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 16 times.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
201 switch (alter_info->ts_cmd_type) {
18858 68 case CREATE_TABLESPACE:
18859 68 break;
18860 87 case ALTER_TABLESPACE:
18861 87 code = ER_ALTER_FILEGROUP_FAILED;
18862 87 break;
18863 2 case DROP_TABLESPACE:
18864 2 code = ER_DROP_FILEGROUP_FAILED;
18865 2 break;
18866 20 case CREATE_UNDO_TABLESPACE:
18867 20 subject = undo_type;
18868 20 break;
18869 16 case ALTER_UNDO_TABLESPACE:
18870 16 code = ER_ALTER_FILEGROUP_FAILED;
18871 16 subject = undo_type;
18872 16 break;
18873 5 case DROP_UNDO_TABLESPACE:
18874 5 code = ER_DROP_FILEGROUP_FAILED;
18875 5 subject = undo_type;
18876 5 break;
18877 3 case CREATE_LOGFILE_GROUP:
18878 case DROP_LOGFILE_GROUP:
18879 case ALTER_LOGFILE_GROUP:
18880 3 subject = "LOGFILE GROUP";
18881 3 break;
18882 case ALTER_ACCESS_MODE_TABLESPACE:
18883 subject = "ACCESS MODE";
18884 break;
18885 case CHANGE_FILE_TABLESPACE:
18886 subject = "CHANGE FILE";
18887 break;
18888 case TS_CMD_NOT_DEFINED:
18889 subject = "UNKNOWN";
18890 break;
18891 }
18892
18893
2/3
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
201 switch (alter_info->ts_cmd_type) {
18894 198 case CREATE_TABLESPACE:
18895 case ALTER_TABLESPACE:
18896 case DROP_TABLESPACE:
18897 case CREATE_UNDO_TABLESPACE:
18898 case ALTER_UNDO_TABLESPACE:
18899 case DROP_UNDO_TABLESPACE:
18900
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
198 ib_errf(thd, IB_LOG_LEVEL_ERROR, code, "%s %s", subject,
18901 alter_info->tablespace_name);
18902 198 break;
18903
18904 3 case CREATE_LOGFILE_GROUP:
18905 case ALTER_ACCESS_MODE_TABLESPACE:
18906 case DROP_LOGFILE_GROUP:
18907 case ALTER_LOGFILE_GROUP:
18908 case CHANGE_FILE_TABLESPACE:
18909 case TS_CMD_NOT_DEFINED:
18910
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_FEATURE_UNSUPPORTED, MYF(0), subject, "by InnoDB");
18911 3 break;
18912 }
18913 }
18914
18915 8801 return error;
18916 8801 }
18917
18918 /** Renames an InnoDB table.
18919 @param[in] from Old name of the table.
18920 @param[in] to New name of the table.
18921 @param[in] from_table_def dd::Table object describing old version
18922 of table.
18923 @param[in,out] to_table_def dd::Table object describing version of
18924 table with new name. Can be updated by SE. Changes are persisted to the
18925 dictionary at statement commit time.
18926 @return 0 or error code */
18927 16687 int ha_innobase::rename_table(const char *from, const char *to,
18928 const dd::Table *from_table_def,
18929 dd::Table *to_table_def) {
18930
1/2
✓ Branch 0 taken 16687 times.
✗ Branch 1 not taken.
16687 THD *thd = ha_thd();
18931
1/2
✓ Branch 0 taken 16687 times.
✗ Branch 1 not taken.
16687 trx_t *trx = check_trx_exists(thd);
18932
1/2
✓ Branch 0 taken 16687 times.
✗ Branch 1 not taken.
16687 TrxInInnoDB trx_in_innodb(trx);
18933
18934
1/2
✓ Branch 0 taken 16687 times.
✗ Branch 1 not taken.
16687 DBUG_TRACE;
18935
3/6
✓ Branch 0 taken 16687 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16687 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 16687 times.
16687 ut_ad(from_table_def->se_private_id() == to_table_def->se_private_id());
18936
5/10
✓ Branch 0 taken 16687 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16687 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16687 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 16687 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 16687 times.
16687 ut_ad(from_table_def->se_private_data().raw_string() ==
18937 to_table_def->se_private_data().raw_string());
18938
18939
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 16684 times.
16687 if (high_level_read_only) {
18940
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE);
18941 3 return HA_ERR_TABLE_READONLY;
18942 }
18943
18944
4/6
✓ Branch 0 taken 16684 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16684 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 16681 times.
16684 if (dict_sys_t::is_dd_table_id(to_table_def->se_private_id())) {
18945
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_NOT_ALLOWED_COMMAND, MYF(0));
18946 3 return HA_ERR_UNSUPPORTED;
18947 }
18948
18949
1/2
✓ Branch 0 taken 16681 times.
✗ Branch 1 not taken.
16681 innobase_register_trx(ht, thd, trx);
18950
18951
1/2
✓ Branch 0 taken 16636 times.
✗ Branch 1 not taken.
16681 return innobase_basic_ddl::rename_impl<dd::Table>(
18952 16636 thd, from, to, from_table_def, to_table_def, nullptr);
18953 16642 }
18954
18955 /** Returns the exact number of records that this client can see using this
18956 handler object.
18957 @return Error code in case something goes wrong.
18958 These errors will abort the current query:
18959 case HA_ERR_LOCK_DEADLOCK:
18960 case HA_ERR_LOCK_TABLE_FULL:
18961 case HA_ERR_LOCK_WAIT_TIMEOUT:
18962 case HA_ERR_QUERY_INTERRUPTED:
18963 For other error codes, the server will fall back to counting records. */
18964
18965 32101 int ha_innobase::records(ha_rows *num_rows) /*!< out: number of rows */
18966 {
18967
1/2
✓ Branch 0 taken 32101 times.
✗ Branch 1 not taken.
32101 DBUG_TRACE;
18968
18969 dberr_t ret;
18970 32101 ulint n_rows = 0; /* Record count in this view */
18971
18972
1/2
✓ Branch 0 taken 32101 times.
✗ Branch 1 not taken.
32101 update_thd();
18973
18974
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 32065 times.
32101 if (dict_table_is_discarded(m_prebuilt->table)) {
18975 36 ib_senderrf(m_user_thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_DISCARDED,
18976
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
36 table->s->table_name.str);
18977
18978 36 *num_rows = HA_POS_ERROR;
18979 36 return HA_ERR_NO_SUCH_TABLE;
18980
18981
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32065 times.
32065 } else if (m_prebuilt->table->ibd_file_missing) {
18982 ib_senderrf(m_user_thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_MISSING,
18983 table->s->table_name.str);
18984
18985 *num_rows = HA_POS_ERROR;
18986 return HA_ERR_TABLESPACE_MISSING;
18987
18988
2/4
✓ Branch 0 taken 32065 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32065 times.
32065 } else if (m_prebuilt->table->is_corrupted()) {
18989 ib_errf(m_user_thd, IB_LOG_LEVEL_WARN, ER_INNODB_INDEX_CORRUPT,
18990 "Table '%s' is corrupt.", table->s->table_name.str);
18991
18992 *num_rows = HA_POS_ERROR;
18993 return HA_ERR_INDEX_CORRUPT;
18994 }
18995
18996
1/2
✓ Branch 0 taken 32065 times.
✗ Branch 1 not taken.
32065 TrxInInnoDB trx_in_innodb(m_prebuilt->trx);
18997
18998 32065 m_prebuilt->trx->op_info = "counting records";
18999
19000
1/2
✓ Branch 0 taken 32065 times.
✗ Branch 1 not taken.
32065 dict_index_t *index = m_prebuilt->table->first_index();
19001
19002
2/4
✓ Branch 0 taken 32065 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32065 times.
32065 ut_ad(index->is_clustered());
19003
19004
1/2
✓ Branch 0 taken 32065 times.
✗ Branch 1 not taken.
32065 m_prebuilt->index_usable = index->is_usable(m_prebuilt->trx);
19005
19006
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 32064 times.
32065 if (!m_prebuilt->index_usable) {
19007 1 *num_rows = HA_POS_ERROR;
19008 1 return HA_ERR_TABLE_DEF_CHANGED;
19009 }
19010
19011 /* (Re)Build the m_prebuilt->mysql_template if it is null to use
19012 the clustered index and just the key, no off-record data. */
19013 32064 m_prebuilt->index = index;
19014
1/2
✓ Branch 0 taken 32064 times.
✗ Branch 1 not taken.
32064 m_prebuilt->clear_search_tuples();
19015 32064 m_prebuilt->read_just_key = 1;
19016
1/2
✓ Branch 0 taken 32064 times.
✗ Branch 1 not taken.
32064 build_template(false);
19017
19018
1/2
✓ Branch 0 taken 32064 times.
✗ Branch 1 not taken.
32064 size_t max_threads = thd_parallel_read_threads(m_prebuilt->trx->mysql_thd);
19019
19020 /* Count the records in the clustered index */
19021 ret =
19022
1/2
✓ Branch 0 taken 32064 times.
✗ Branch 1 not taken.
32064 row_scan_index_for_mysql(m_prebuilt, index, max_threads, false, &n_rows);
19023
1/2
✓ Branch 0 taken 32064 times.
✗ Branch 1 not taken.
32064 reset_template();
19024
3/4
✓ Branch 0 taken 32032 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
32064 switch (ret) {
19025 32032 case DB_SUCCESS:
19026 32032 break;
19027 30 case DB_DEADLOCK:
19028 case DB_LOCK_TABLE_FULL:
19029 case DB_LOCK_WAIT_TIMEOUT:
19030 30 *num_rows = HA_POS_ERROR;
19031
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 return convert_error_code_to_mysql(ret, 0, m_user_thd);
19032 2 case DB_INTERRUPTED:
19033 2 *num_rows = HA_POS_ERROR;
19034 2 return HA_ERR_QUERY_INTERRUPTED;
19035 default:
19036 /* No other error besides the three below is returned from
19037 row_scan_index_for_mysql(). Make a debug catch. */
19038 *num_rows = HA_POS_ERROR;
19039 return -1;
19040 }
19041
19042 32032 m_prebuilt->trx->op_info = "";
19043
19044
2/4
✓ Branch 0 taken 32032 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32032 times.
32032 if (thd_killed(m_user_thd)) {
19045 *num_rows = HA_POS_ERROR;
19046 return HA_ERR_QUERY_INTERRUPTED;
19047 }
19048
19049 32032 *num_rows = n_rows;
19050 32032 return 0;
19051 32101 }
19052
19053 /** Estimates the number of index records in a range.
19054 @return estimated number of rows */
19055
19056 497841 ha_rows ha_innobase::records_in_range(
19057 uint keynr, /*!< in: index number */
19058 key_range *min_key, /*!< in: start key value of the
19059 range, may also be 0 */
19060 key_range *max_key) /*!< in: range end key val, may
19061 also be 0 */
19062 {
19063 KEY *key;
19064 dict_index_t *index;
19065 dtuple_t *range_start;
19066 dtuple_t *range_end;
19067 int64_t n_rows;
19068 page_cur_mode_t mode1;
19069 page_cur_mode_t mode2;
19070 mem_heap_t *heap;
19071
19072
1/2
✓ Branch 0 taken 497844 times.
✗ Branch 1 not taken.
497841 DBUG_TRACE;
19073
19074
3/6
✓ Branch 0 taken 497844 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 497844 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 497844 times.
497844 ut_a(m_prebuilt->trx == thd_to_trx(ha_thd()));
19075
19076 497844 m_prebuilt->trx->op_info = "estimating records in index range";
19077
19078
1/2
✓ Branch 0 taken 497843 times.
✗ Branch 1 not taken.
497844 TrxInInnoDB trx_in_innodb(m_prebuilt->trx);
19079
19080 497843 active_index = keynr;
19081
19082 497843 key = table->key_info + active_index;
19083
19084
1/2
✓ Branch 0 taken 497844 times.
✗ Branch 1 not taken.
497843 index = innobase_get_index(keynr);
19085
19086 /* There exists possibility of not being able to find requested
19087 index due to inconsistency between MySQL and InoDB dictionary info.
19088 Necessary message should have been printed in innobase_get_index() */
19089
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 497843 times.
497844 if (dict_table_is_discarded(m_prebuilt->table)) {
19090 n_rows = HA_POS_ERROR;
19091 goto func_exit;
19092 }
19093
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 497843 times.
497843 if (!index) {
19094 n_rows = HA_POS_ERROR;
19095 goto func_exit;
19096 }
19097
3/4
✓ Branch 0 taken 497844 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 497836 times.
497843 if (index->is_corrupted()) {
19098 8 n_rows = HA_ERR_INDEX_CORRUPT;
19099 8 goto func_exit;
19100 }
19101
3/4
✓ Branch 0 taken 497836 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 497834 times.
497836 if (!index->is_usable(m_prebuilt->trx)) {
19102 2 n_rows = HA_ERR_TABLE_DEF_CHANGED;
19103 2 goto func_exit;
19104 }
19105
19106 995667 heap = mem_heap_create(
19107
1/2
✓ Branch 0 taken 497833 times.
✗ Branch 1 not taken.
497834 2 * (key->actual_key_parts * sizeof(dfield_t) + sizeof(dtuple_t)),
19108 UT_LOCATION_HERE);
19109
19110
1/2
✓ Branch 0 taken 497834 times.
✗ Branch 1 not taken.
497833 range_start = dtuple_create(heap, key->actual_key_parts);
19111
1/2
✓ Branch 0 taken 497834 times.
✗ Branch 1 not taken.
497834 dict_index_copy_types(range_start, index, key->actual_key_parts);
19112
19113
1/2
✓ Branch 0 taken 497834 times.
✗ Branch 1 not taken.
497834 range_end = dtuple_create(heap, key->actual_key_parts);
19114
1/2
✓ Branch 0 taken 497833 times.
✗ Branch 1 not taken.
497834 dict_index_copy_types(range_end, index, key->actual_key_parts);
19115
19116
4/4
✓ Branch 0 taken 490119 times.
✓ Branch 1 taken 7714 times.
✓ Branch 2 taken 490119 times.
✓ Branch 3 taken 7714 times.
987952 row_sel_convert_mysql_key_to_innobase(
19117
1/2
✓ Branch 0 taken 497834 times.
✗ Branch 1 not taken.
497833 range_start, m_prebuilt->srch_key_val1, m_prebuilt->srch_key_val_len,
19118 index, (byte *)(min_key ? min_key->key : (const uchar *)nullptr),
19119 490119 (ulint)(min_key ? min_key->length : 0));
19120
19121
3/4
✓ Branch 0 taken 490120 times.
✓ Branch 1 taken 7714 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 497834 times.
497834 assert(min_key ? range_start->n_fields > 0 : range_start->n_fields == 0);
19122
19123
4/4
✓ Branch 0 taken 415589 times.
✓ Branch 1 taken 82245 times.
✓ Branch 2 taken 415589 times.
✓ Branch 3 taken 82245 times.
913423 row_sel_convert_mysql_key_to_innobase(
19124
1/2
✓ Branch 0 taken 497834 times.
✗ Branch 1 not taken.
497834 range_end, m_prebuilt->srch_key_val2, m_prebuilt->srch_key_val_len, index,
19125 (byte *)(max_key ? max_key->key : (const uchar *)nullptr),
19126 415589 (ulint)(max_key ? max_key->length : 0));
19127
19128
3/4
✓ Branch 0 taken 415589 times.
✓ Branch 1 taken 82245 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 497834 times.
497834 assert(max_key ? range_end->n_fields > 0 : range_end->n_fields == 0);
19129
19130
3/4
✓ Branch 0 taken 490120 times.
✓ Branch 1 taken 7714 times.
✓ Branch 2 taken 497832 times.
✗ Branch 3 not taken.
497834 mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag
19131 : HA_READ_KEY_EXACT);
19132
19133
3/4
✓ Branch 0 taken 415586 times.
✓ Branch 1 taken 82246 times.
✓ Branch 2 taken 497832 times.
✗ Branch 3 not taken.
497832 mode2 = convert_search_mode_to_innobase(max_key ? max_key->flag
19134 : HA_READ_KEY_EXACT);
19135
19136
2/4
✓ Branch 0 taken 497832 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 497832 times.
✗ Branch 3 not taken.
497832 if (mode1 != PAGE_CUR_UNSUPP && mode2 != PAGE_CUR_UNSUPP) {
19137
3/4
✓ Branch 0 taken 497834 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 568 times.
✓ Branch 3 taken 497266 times.
497832 if (dict_index_is_spatial(index)) {
19138 /*Only min_key used in spatial index. */
19139
1/2
✓ Branch 0 taken 568 times.
✗ Branch 1 not taken.
568 n_rows = rtr_estimate_n_rows_in_range(index, range_start, mode1);
19140 } else {
19141
1/2
✓ Branch 0 taken 497266 times.
✗ Branch 1 not taken.
497266 n_rows = btr_estimate_n_rows_in_range(index, range_start, mode1,
19142 range_end, mode2);
19143 }
19144 } else {
19145 n_rows = HA_POS_ERROR;
19146 }
19147
19148
1/2
✓ Branch 0 taken 497834 times.
✗ Branch 1 not taken.
497834 mem_heap_free(heap);
19149
19150
5/8
✓ Branch 0 taken 497834 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 497686 times.
✓ Branch 3 taken 148 times.
✓ Branch 4 taken 148 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 148 times.
✗ Branch 7 not taken.
497834 DBUG_EXECUTE_IF(
19151 "print_btr_estimate_n_rows_in_range_return_value",
19152 push_warning_printf(ha_thd(), Sql_condition::SL_WARNING, ER_NO_DEFAULT,
19153 "btr_estimate_n_rows_in_range(): %" PRId64, n_rows););
19154
19155 497686 func_exit:
19156
19157 497844 m_prebuilt->trx->op_info = (char *)"";
19158
19159 /* The MySQL optimizer seems to believe an estimate of 0 rows is
19160 always accurate and may return the result 'Empty set' based on that.
19161 The accuracy is not guaranteed, and even if it were, for a locking
19162 read we should anyway perform the search to set the next-key lock.
19163 Add 1 to the value to make sure MySQL does not make the assumption! */
19164
19165
2/2
✓ Branch 0 taken 206090 times.
✓ Branch 1 taken 291754 times.
497844 if (n_rows == 0) {
19166 206090 n_rows = 1;
19167 }
19168
19169 497844 return (ha_rows)n_rows;
19170 497844 }
19171
19172 /** Gives an UPPER BOUND to the number of rows in a table. This is used in
19173 filesort.cc.
19174 @return upper bound of rows */
19175
19176 124086 ha_rows ha_innobase::estimate_rows_upper_bound() {
19177 const dict_index_t *index;
19178 ulonglong estimate;
19179 ulonglong local_data_file_length;
19180
19181
1/2
✓ Branch 0 taken 124087 times.
✗ Branch 1 not taken.
124086 DBUG_TRACE;
19182
19183 /* We do not know if MySQL can call this function before calling
19184 external_lock(). To be safe, update the thd of the current table
19185 handle. */
19186
19187
2/4
✓ Branch 0 taken 124087 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 124087 times.
✗ Branch 3 not taken.
124087 update_thd(ha_thd());
19188
19189
1/2
✓ Branch 0 taken 124087 times.
✗ Branch 1 not taken.
124087 TrxInInnoDB trx_in_innodb(m_prebuilt->trx);
19190
19191 124087 m_prebuilt->trx->op_info = "calculating upper bound for table rows";
19192
19193
1/2
✓ Branch 0 taken 124087 times.
✗ Branch 1 not taken.
124087 index = m_prebuilt->table->first_index();
19194
19195 124087 ulint stat_n_leaf_pages = index->stat_n_leaf_pages;
19196
19197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 124087 times.
124087 ut_a(stat_n_leaf_pages > 0);
19198
19199 124087 local_data_file_length = ((ulonglong)stat_n_leaf_pages) * UNIV_PAGE_SIZE;
19200
19201 /* Calculate a minimum length for a clustered index record and from
19202 that an upper bound for the number of rows. Since we only calculate
19203 new statistics in row0mysql.cc when a table has grown by a threshold
19204 factor, we must add a safety factor 2 in front of the formula below. */
19205
19206
1/2
✓ Branch 0 taken 124087 times.
✗ Branch 1 not taken.
124087 estimate = 2 * local_data_file_length / dict_index_calc_min_rec_len(index);
19207
19208 124087 m_prebuilt->trx->op_info = "";
19209
19210 /* Set num_rows less than MERGEBUFF to simulate the case where we do
19211 not have enough space to merge the externally sorted file blocks. */
19212
2/6
✓ Branch 0 taken 124087 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 124087 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
124087 DBUG_EXECUTE_IF("set_num_rows_lt_MERGEBUFF", estimate = 2;
19213 DBUG_SET("-d,set_num_rows_lt_MERGEBUFF"););
19214
19215 124087 return (ha_rows)estimate;
19216 124087 }
19217
19218 /** How many seeks it will take to read through the table. This is to be
19219 comparable to the number returned by records_in_range so that we can
19220 decide if we should scan the table or use keys.
19221 @return estimated time measured in disk seeks */
19222
19223 42858758 double ha_innobase::scan_time() {
19224 /* Since MySQL seems to favor table scans too much over index
19225 searches, we pretend that a sequential read takes the same time
19226 as a random disk read, that is, we do not divide the following
19227 by 10, which would be physically realistic. */
19228
19229 /* The locking below is disabled for performance reasons. Without
19230 it we could end up returning uninitialized value to the caller,
19231 which in the worst case could make some query plan go bogus or
19232 issue a Valgrind warning. */
19233
19234
2/2
✓ Branch 0 taken 1759 times.
✓ Branch 1 taken 42856999 times.
42858758 if (m_prebuilt == nullptr) {
19235 /* In case of derived table, Optimizer will try to fetch stat
19236 for table even before table is create or open. In such
19237 cases return default value of 1.
19238 TODO: This will be further improved to return some approximate
19239 estimate but that would also needs pre-population of stats
19240 structure. As of now approach is in sync with MyISAM. */
19241 1759 return (ulonglong2double(stats.data_file_length) / IO_SIZE + 2);
19242 }
19243
19244 ulint stat_clustered_index_size;
19245
19246
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42857193 times.
42856999 ut_a(m_prebuilt->table->stat_initialized);
19247
19248 42857193 stat_clustered_index_size = m_prebuilt->table->stat_clustered_index_size;
19249
19250 42857193 return ((double)stat_clustered_index_size);
19251 }
19252
19253 /** Calculate the time it takes to read a set of ranges through an index
19254 This enables us to optimise reads for clustered indexes.
19255 @return estimated time measured in disk seeks */
19256
19257 748655 double ha_innobase::read_time(
19258 uint index, /*!< in: key number */
19259 uint ranges, /*!< in: how many ranges */
19260 ha_rows rows) /*!< in: estimated number of rows in the ranges */
19261 {
19262 ha_rows total_rows;
19263
19264
2/2
✓ Branch 0 taken 357579 times.
✓ Branch 1 taken 391076 times.
748655 if (index != table->s->primary_key) {
19265 /* Not clustered */
19266 357579 return (handler::read_time(index, ranges, rows));
19267 }
19268
19269
2/2
✓ Branch 0 taken 265822 times.
✓ Branch 1 taken 125254 times.
391076 if (rows <= 2) {
19270 265822 return ((double)rows);
19271 }
19272
19273 /* Assume that the read time is proportional to the scan time for all
19274 rows + at most one seek per range. */
19275
19276 125254 double time_for_scan = scan_time();
19277
19278
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 125286 times.
125286 if ((total_rows = estimate_rows_upper_bound()) < rows) {
19279 1 return (time_for_scan);
19280 }
19281
19282 125286 return (ranges + (double)rows / (double)total_rows * time_for_scan);
19283 }
19284
19285 /** Return the size of the InnoDB memory buffer. */
19286
19287 2703169 longlong ha_innobase::get_memory_buffer_size() const {
19288 2703169 return (srv_buf_pool_curr_size);
19289 }
19290
19291 /** Update the system variable with the given value of the InnoDB
19292 buffer pool size.
19293 @param[in] buf_pool_size given value of buffer pool size.*/
19294 23 void innodb_set_buf_pool_size(long long buf_pool_size) {
19295 23 srv_buf_pool_curr_size = buf_pool_size;
19296 23 }
19297
19298 /** Calculates the key number used inside MySQL for an Innobase index. We
19299 will first check the "index translation table" for a match of the index to
19300 get the index number. If there does not exist an "index translation table",
19301 or not able to find the index in the translation table, then we will fall
19302 back to the traditional way of looping through dict_index_t list to find a
19303 match. In this case, we have to take into account if we generated a
19304 default clustered index for the table
19305 @return the key number used inside MySQL */
19306 914422 static int innobase_get_mysql_key_number_for_index(
19307 INNOBASE_SHARE *share, /*!< in: share structure for index
19308 translation table. */
19309 const TABLE *table, /*!< in: table in MySQL data
19310 dictionary */
19311 dict_table_t *ib_table, /*!< in: table in InnoDB data
19312 dictionary */
19313 const dict_index_t *index) /*!< in: index */
19314 {
19315 const dict_index_t *ind;
19316 unsigned int i;
19317
19318 /* If index does not belong to the table object of share structure
19319 (ib_table comes from the share structure) search the index->table
19320 object instead */
19321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 914422 times.
914422 if (index->table != ib_table) {
19322 i = 0;
19323 ind = index->table->first_index();
19324
19325 while (index != ind) {
19326 ind = ind->next();
19327 i++;
19328 }
19329
19330 if (row_table_got_default_clust_index(index->table)) {
19331 ut_a(i > 0);
19332 i--;
19333 }
19334
19335 return (i);
19336 }
19337
19338 /* If index translation table exists, we will first check
19339 the index through index translation table for a match. */
19340
1/2
✓ Branch 0 taken 914422 times.
✗ Branch 1 not taken.
914422 if (share->idx_trans_tbl.index_mapping != nullptr) {
19341
1/2
✓ Branch 0 taken 915076 times.
✗ Branch 1 not taken.
915076 for (i = 0; i < share->idx_trans_tbl.index_count; i++) {
19342
2/2
✓ Branch 0 taken 914422 times.
✓ Branch 1 taken 654 times.
915076 if (share->idx_trans_tbl.index_mapping[i] == index) {
19343 914422 return (i);
19344 }
19345 }
19346
19347 /* Print an error message if we cannot find the index
19348 in the "index translation table". */
19349 if (index->is_committed()) {
19350 log_errlog(ERROR_LEVEL, ER_INNODB_FAILED_TO_FIND_IDX, index->name());
19351 }
19352 }
19353
19354 /* If we do not have an "index translation table", or not able
19355 to find the index in the translation table, we'll directly find
19356 matching index with information from mysql TABLE structure and
19357 InnoDB dict_index_t list */
19358 for (i = 0; i < table->s->keys; i++) {
19359 ind = dict_table_get_index_on_name(ib_table, table->key_info[i].name);
19360
19361 if (index == ind) {
19362 return (i);
19363 }
19364 }
19365
19366 /* Loop through each index of the table and lock them */
19367 for (ind = ib_table->first_index(); ind != nullptr; ind = ind->next()) {
19368 if (index == ind) {
19369 /* Temp index is internal to InnoDB, that is
19370 not present in the MySQL index list, so no
19371 need to print such mismatch warning. */
19372 if (index->is_committed()) {
19373 log_errlog(WARNING_LEVEL, ER_INNODB_INTERNAL_INDEX, index->name());
19374 }
19375 return (-1);
19376 }
19377 }
19378
19379 ut_error;
19380 }
19381
19382 /** Calculate Record Per Key value.
19383 Need to exclude the NULL value if innodb_stats_method is set to "nulls_ignored"
19384 @param[in] index InnoDB index.
19385 @param[in] i The column we are calculating rec per key.
19386 @param[in] records Estimated total records.
19387 @return estimated record per key value */
19388 41934152 rec_per_key_t innodb_rec_per_key(const dict_index_t *index, ulint i,
19389 ha_rows records) {
19390 rec_per_key_t rec_per_key;
19391 uint64_t n_diff;
19392
19393
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41934169 times.
41934152 ut_a(index->table->stat_initialized);
19394
19395
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41934153 times.
41934169 ut_ad(i < dict_index_get_n_unique(index));
19396
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41934200 times.
41934153 ut_ad(!dict_index_is_spatial(index));
19397
19398
2/2
✓ Branch 0 taken 5522832 times.
✓ Branch 1 taken 36411368 times.
41934200 if (records == 0) {
19399 /* "Records per key" is meaningless for empty tables.
19400 Return 1.0 because that is most convenient to the Optimizer. */
19401 5522832 return (1.0);
19402 }
19403
19404 36411368 n_diff = index->stat_n_diff_key_vals[i];
19405
19406
2/2
✓ Branch 0 taken 5780419 times.
✓ Branch 1 taken 30630949 times.
36411368 if (n_diff == 0) {
19407 5780419 rec_per_key = static_cast<rec_per_key_t>(records);
19408
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 30630941 times.
30630949 } else if (srv_innodb_stats_method == SRV_STATS_NULLS_IGNORED) {
19409 uint64_t n_null;
19410 uint64_t n_non_null;
19411
19412 8 n_non_null = index->stat_n_non_null_key_vals[i];
19413
19414 /* In theory, index->stat_n_non_null_key_vals[i]
19415 should always be less than the number of records.
19416 Since this is statistics value, the value could
19417 have slight discrepancy. But we will make sure
19418 the number of null values is not a negative number. */
19419
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (records < n_non_null) {
19420 n_null = 0;
19421 } else {
19422 8 n_null = records - n_non_null;
19423 }
19424
19425 /* If the number of NULL values is the same as or
19426 large than that of the distinct values, we could
19427 consider that the table consists mostly of NULL value.
19428 Set rec_per_key to 1. */
19429
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (n_diff <= n_null) {
19430 8 rec_per_key = 1.0;
19431 } else {
19432 /* Need to exclude rows with NULL values from
19433 rec_per_key calculation */
19434 rec_per_key =
19435 static_cast<rec_per_key_t>(records - n_null) / (n_diff - n_null);
19436 }
19437 } else {
19438 #ifdef UNIV_DEBUG
19439
2/2
✓ Branch 0 taken 4562853 times.
✓ Branch 1 taken 26068088 times.
30630941 if (!index->table->is_dd_table) {
19440
2/2
✓ Branch 0 taken 4457052 times.
✓ Branch 1 taken 105801 times.
4562853 DEBUG_SYNC_C("after_checking_for_0");
19441 }
19442 #endif /* UNIV_DEBUG */
19443 30630981 rec_per_key = static_cast<rec_per_key_t>(records) / n_diff;
19444 }
19445
19446
2/2
✓ Branch 0 taken 2749767 times.
✓ Branch 1 taken 33661641 times.
36411408 if (rec_per_key < 1.0) {
19447 /* Values below 1.0 are meaningless and must be due to the
19448 stats being imprecise. */
19449 2749767 rec_per_key = 1.0;
19450 }
19451
19452 36411408 return (rec_per_key);
19453 }
19454
19455 /** Read the auto_increment counter of a table, using the AUTOINC lock
19456 irrespective of innodb_autoinc_lock_mode.
19457 @param[in,out] innodb_table InnoDB table object
19458 @param[in] print_note Print note if not an I_S query.
19459 @return the autoinc value */
19460 17649 static ulonglong innobase_peek_autoinc(dict_table_t *innodb_table,
19461 bool print_note) {
19462 ulonglong auto_inc;
19463
19464
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17649 times.
17649 ut_a(innodb_table != nullptr);
19465
19466 17649 dict_table_autoinc_lock(innodb_table);
19467
19468 17649 auto_inc = dict_table_autoinc_read(innodb_table);
19469
19470
3/4
✓ Branch 0 taken 3008 times.
✓ Branch 1 taken 14641 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3008 times.
17649 if (auto_inc == 0 && print_note) {
19471 ib::info(ER_IB_MSG_569) << "AUTOINC next value generation is disabled for "
19472 << innodb_table->name;
19473 }
19474
19475 17649 dict_table_autoinc_unlock(innodb_table);
19476
19477 17649 return (auto_inc);
19478 }
19479
19480 /** Calculate delete length statistic.
19481 @param[in] ib_table table object
19482 @param[in,out] stats stats structure to hold calculated values
19483 @param[in,out] thd user thread handle (for issuing warnings) */
19484 24107 static void calculate_delete_length_stat(const dict_table_t *ib_table,
19485 ha_statistics *stats, THD *thd) {
19486 uintmax_t avail_space;
19487
19488 24107 avail_space = fsp_get_available_space_in_free_extents(ib_table->space);
19489
19490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24107 times.
24107 if (avail_space == UINTMAX_MAX) {
19491 char errbuf[MYSYS_STRERROR_SIZE];
19492 std::ostringstream err_msg;
19493 err_msg << "InnoDB: Trying to get the free space for table "
19494 << ib_table->name
19495 << " but its tablespace has been"
19496 " discarded or the .ibd file is missing. Setting"
19497 " the free space to zero. (errno: "
19498 << errno << " - " << my_strerror(errbuf, sizeof(errbuf), errno)
19499 << ")";
19500
19501 push_warning(thd, Sql_condition::SL_WARNING, ER_CANT_GET_STAT,
19502 err_msg.str().c_str());
19503
19504 stats->delete_length = 0;
19505 } else {
19506 24107 stats->delete_length = avail_space * 1024;
19507 }
19508 24107 }
19509
19510 /** Calculate stats based on index size.
19511 @param[in] ib_table table object
19512 @param[in] n_rows number of rows
19513 @param[in] stat_clustered_index_size clustered index size
19514 @param[in] stat_sum_of_other_index_sizes sum of non-clustered index sizes
19515 @param[in,out] stats the stats structure to hold
19516 calculated values */
19517 8270185 static void calculate_index_size_stats(const dict_table_t *ib_table,
19518 uint64_t n_rows,
19519 ulint stat_clustered_index_size,
19520 ulint stat_sum_of_other_index_sizes,
19521 ha_statistics *stats) {
19522
1/2
✓ Branch 0 taken 8270349 times.
✗ Branch 1 not taken.
8270185 const page_size_t &page_size = dict_table_page_size(ib_table);
19523
19524 8270349 stats->records = static_cast<ha_rows>(n_rows);
19525 8270322 stats->data_file_length =
19526
1/2
✓ Branch 0 taken 8270322 times.
✗ Branch 1 not taken.
8270349 static_cast<ulonglong>(stat_clustered_index_size) * page_size.physical();
19527 8270356 stats->index_file_length =
19528 8270356 static_cast<ulonglong>(stat_sum_of_other_index_sizes) *
19529
1/2
✓ Branch 0 taken 8270356 times.
✗ Branch 1 not taken.
8270322 page_size.physical();
19530
2/2
✓ Branch 0 taken 340054 times.
✓ Branch 1 taken 7930302 times.
8270356 if (stats->records == 0) {
19531 340054 stats->mean_rec_length = 0;
19532 } else {
19533 7930302 stats->mean_rec_length =
19534 7930302 static_cast<ulong>(stats->data_file_length / stats->records);
19535 }
19536 8270356 }
19537
19538 /** Estimate what percentage of an index's pages are cached in the buffer pool
19539 @param[in] index index whose pages to look up
19540 @return a real number in [0.0, 1.0] designating the percentage of cached pages
19541 */
19542 23248922 inline double index_pct_cached(const dict_index_t *index) {
19543 23248922 const ulint n_leaf = index->stat_n_leaf_pages;
19544
19545
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23248922 times.
23248922 if (n_leaf == 0) {
19546 return (0.0);
19547 }
19548
19549 const uint64_t n_in_mem =
19550
1/2
✓ Branch 0 taken 23249072 times.
✗ Branch 1 not taken.
23248922 buf_stat_per_index->get(index_id_t(index->space, index->id));
19551
19552 23249072 const double ratio = static_cast<double>(n_in_mem) / n_leaf;
19553
19554 23249072 return (std::max(std::min(ratio, 1.0), 0.0));
19555 }
19556
19557 /** Returns statistics information of the table to the MySQL interpreter, in
19558 various fields of the handle object.
19559 @param[in] flag what information is requested
19560 @param[in] is_analyze True if called from "::analyze()".
19561 @return HA_ERR_* error code or 0 */
19562 9310193 int ha_innobase::info_low(uint flag, bool is_analyze) {
19563 dict_table_t *ib_table;
19564 uint64_t n_rows;
19565
19566
1/2
✓ Branch 0 taken 9310504 times.
✗ Branch 1 not taken.
9310193 DBUG_TRACE;
19567
19568
3/4
✓ Branch 0 taken 9134584 times.
✓ Branch 1 taken 175920 times.
✓ Branch 2 taken 9134607 times.
✗ Branch 3 not taken.
9310504 DEBUG_SYNC_C("ha_innobase_info_low");
19569
19570 /* If we are forcing recovery at a high level, we will suppress
19571 statistics calculation on tables, because that may crash the
19572 server if an index is badly corrupted. */
19573
19574 /* We do not know if MySQL can call this function before calling
19575 external_lock(). To be safe, update the thd of the current table
19576 handle. */
19577
19578
2/4
✓ Branch 0 taken 9310517 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9310501 times.
✗ Branch 3 not taken.
9310527 update_thd(ha_thd());
19579
19580 9310501 m_prebuilt->trx->op_info = (char *)"returning various info to MySQL";
19581
19582 9310501 ib_table = m_prebuilt->table;
19583
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9310481 times.
9310501 assert(ib_table->n_ref_count > 0);
19584
19585
2/2
✓ Branch 0 taken 152560 times.
✓ Branch 1 taken 9157921 times.
9310481 if (flag & HA_STATUS_TIME) {
19586
4/4
✓ Branch 0 taken 140187 times.
✓ Branch 1 taken 12373 times.
✓ Branch 2 taken 72 times.
✓ Branch 3 taken 140115 times.
152560 if (is_analyze || innobase_stats_on_metadata) {
19587 dict_stats_upd_option_t opt;
19588 dberr_t ret;
19589
19590 12445 m_prebuilt->trx->op_info = "updating table statistics";
19591
19592
3/4
✓ Branch 0 taken 12445 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12225 times.
✓ Branch 3 taken 220 times.
12445 if (dict_stats_is_persistent_enabled(ib_table)) {
19593
2/2
✓ Branch 0 taken 12153 times.
✓ Branch 1 taken 72 times.
12225 if (is_analyze) {
19594 /* If this table is already queued for background analyze, remove it
19595 from the queue as we are about to do the same */
19596
2/2
✓ Branch 0 taken 12151 times.
✓ Branch 1 taken 2 times.
12153 if (!srv_read_only_mode) {
19597
1/2
✓ Branch 0 taken 12151 times.
✗ Branch 1 not taken.
12151 dict_mutex_enter_for_mysql();
19598
1/2
✓ Branch 0 taken 12151 times.
✗ Branch 1 not taken.
12151 dict_stats_recalc_pool_del(ib_table);
19599
1/2
✓ Branch 0 taken 12151 times.
✗ Branch 1 not taken.
12151 dict_mutex_exit_for_mysql();
19600 }
19601 12153 opt = DICT_STATS_RECALC_PERSISTENT;
19602 } else {
19603 /* This is e.g. 'SHOW INDEXES', fetch
19604 the persistent stats from disk. */
19605 72 opt = DICT_STATS_FETCH_ONLY_IF_NOT_IN_MEMORY;
19606 }
19607 } else {
19608 220 opt = DICT_STATS_RECALC_TRANSIENT;
19609 }
19610
19611
2/4
✓ Branch 0 taken 12445 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12445 times.
12445 ut_ad(!dict_sys_mutex_own());
19612
1/2
✓ Branch 0 taken 12445 times.
✗ Branch 1 not taken.
12445 ret = dict_stats_update(ib_table, opt);
19613
19614
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12445 times.
12445 if (ret != DB_SUCCESS) {
19615 m_prebuilt->trx->op_info = "";
19616 return HA_ERR_GENERIC;
19617 }
19618
19619 12445 m_prebuilt->trx->op_info = "returning various info to MySQL";
19620 }
19621
19622 152560 stats.update_time = (ulong)std::chrono::system_clock::to_time_t(
19623 305120 ib_table->update_time.load());
19624 }
19625
19626
2/2
✓ Branch 0 taken 8266933 times.
✓ Branch 1 taken 1043548 times.
9310481 if (flag & HA_STATUS_VARIABLE) {
19627 ulint stat_clustered_index_size;
19628 ulint stat_sum_of_other_index_sizes;
19629
19630
2/2
✓ Branch 0 taken 40935 times.
✓ Branch 1 taken 8225998 times.
8266933 if (!(flag & HA_STATUS_NO_LOCK)) {
19631
1/2
✓ Branch 0 taken 40935 times.
✗ Branch 1 not taken.
40935 dict_table_stats_lock(ib_table, RW_S_LATCH);
19632 }
19633
19634
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8266765 times.
8266933 ut_a(ib_table->stat_initialized);
19635
19636 8266765 n_rows = ib_table->stat_n_rows;
19637
19638 8266765 stat_clustered_index_size = ib_table->stat_clustered_index_size;
19639
19640 8266765 stat_sum_of_other_index_sizes = ib_table->stat_sum_of_other_index_sizes;
19641
19642
2/2
✓ Branch 0 taken 40935 times.
✓ Branch 1 taken 8225830 times.
8266765 if (!(flag & HA_STATUS_NO_LOCK)) {
19643
1/2
✓ Branch 0 taken 40935 times.
✗ Branch 1 not taken.
40935 dict_table_stats_unlock(ib_table, RW_S_LATCH);
19644 }
19645
19646 /*
19647 The MySQL optimizer seems to assume in a left join that n_rows
19648 is an accurate estimate if it is zero. Of course, it is not,
19649 since we do not have any locks on the rows yet at this phase.
19650 Since SHOW TABLE STATUS seems to call this function with the
19651 HA_STATUS_TIME flag set, while the left join optimizer does not
19652 set that flag, we add one to a zero value if the flag is not
19653 set. That way SHOW TABLE STATUS will show the best estimate,
19654 while the optimizer never sees the table empty.
19655 However, if it is internal temporary table used by optimizer,
19656 the count should be accurate */
19657
19658
4/4
✓ Branch 0 taken 2018218 times.
✓ Branch 1 taken 6248547 times.
✓ Branch 2 taken 1897106 times.
✓ Branch 3 taken 121112 times.
8266765 if (n_rows == 0 && !(flag & HA_STATUS_TIME) &&
19659
2/2
✓ Branch 0 taken 1679726 times.
✓ Branch 1 taken 217380 times.
1897106 table_share->table_category != TABLE_CATEGORY_TEMPORARY) {
19660 1679726 n_rows++;
19661 }
19662
19663 8266765 stats.records = (ha_rows)n_rows;
19664 8266765 stats.deleted = 0;
19665
19666
1/2
✓ Branch 0 taken 8266928 times.
✗ Branch 1 not taken.
8266765 calculate_index_size_stats(ib_table, n_rows, stat_clustered_index_size,
19667 stat_sum_of_other_index_sizes, &stats);
19668
19669 /* Since fsp_get_available_space_in_free_extents() is
19670 acquiring latches inside InnoDB, we do not call it if we
19671 are asked by MySQL to avoid locking. Another reason to
19672 avoid the call is that it uses quite a lot of CPU.
19673 See Bug#38185. */
19674
4/4
✓ Branch 0 taken 40935 times.
✓ Branch 1 taken 8225993 times.
✓ Branch 2 taken 20662 times.
✓ Branch 3 taken 20273 times.
8266928 if (flag & HA_STATUS_NO_LOCK || !(flag & HA_STATUS_VARIABLE_EXTRA)) {
19675 /* We do not update delete_length if no
19676 locking is requested so the "old" value can
19677 remain. delete_length is initialized to 0 in
19678 the ha_statistics' constructor. Also we only
19679 need delete_length to be set when
19680 HA_STATUS_VARIABLE_EXTRA is set */
19681
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20662 times.
20662 } else if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
19682 /* Avoid accessing the tablespace if
19683 innodb_crash_recovery is set to a high value. */
19684 stats.delete_length = 0;
19685 } else {
19686
2/4
✓ Branch 0 taken 20662 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20602 times.
✗ Branch 3 not taken.
20662 calculate_delete_length_stat(ib_table, &stats, ha_thd());
19687 }
19688
19689 8266868 stats.check_time = 0;
19690 8266868 stats.mrr_length_per_rec = ref_length + sizeof(void *);
19691 }
19692
19693 /* Verify the number of indexes in InnoDB and MySQL
19694 matches up. If m_prebuilt->clust_index_was_generated
19695 holds, InnoDB defines GEN_CLUST_INDEX internally. */
19696
1/2
✓ Branch 0 taken 9310254 times.
✗ Branch 1 not taken.
9310416 ulint num_innodb_index = UT_LIST_GET_LEN(ib_table->indexes) -
19697 9310254 m_prebuilt->clust_index_was_generated;
19698
2/2
✓ Branch 0 taken 5719 times.
✓ Branch 1 taken 9304535 times.
9310254 if (table->s->keys < num_innodb_index) {
19699 /* If there are too many indexes defined
19700 inside InnoDB, ignore those that are being
19701 created, because MySQL will only consider
19702 the fully built indexes here. */
19703
19704
6/10
✓ Branch 0 taken 5719 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5719 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 27549 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 33268 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 27549 times.
✓ Branch 9 taken 5719 times.
33268 for (const dict_index_t *index : ib_table->indexes) {
19705 /* First, online index creation is
19706 completed inside InnoDB, and then
19707 MySQL attempts to upgrade the
19708 meta-data lock so that it can rebuild
19709 the .frm file. If we get here in that
19710 time frame, dict_index_is_online_ddl()
19711 would not hold and the index would
19712 still not be included in TABLE_SHARE. */
19713
3/4
✓ Branch 0 taken 27549 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 142 times.
✓ Branch 3 taken 27407 times.
27549 if (!index->is_committed()) {
19714 142 num_innodb_index--;
19715 }
19716 }
19717
19718
4/4
✓ Branch 0 taken 5586 times.
✓ Branch 1 taken 133 times.
✓ Branch 2 taken 5586 times.
✓ Branch 3 taken 133 times.
11305 if (table->s->keys < num_innodb_index &&
19719
2/4
✓ Branch 0 taken 5586 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5586 times.
✗ Branch 3 not taken.
5586 innobase_fts_check_doc_id_index(ib_table, nullptr, nullptr) ==
19720 FTS_EXIST_DOC_ID_INDEX) {
19721 5586 num_innodb_index--;
19722 }
19723 }
19724
19725
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9310254 times.
9310254 if (table->s->keys != num_innodb_index) {
19726 log_errlog(ERROR_LEVEL, ER_INNODB_IDX_CNT_MORE_THAN_DEFINED_IN_MYSQL,
19727 ib_table->name.m_name, num_innodb_index, table->s->keys);
19728 }
19729
19730
2/2
✓ Branch 0 taken 169881 times.
✓ Branch 1 taken 9140373 times.
9310254 if (!(flag & HA_STATUS_NO_LOCK)) {
19731
1/2
✓ Branch 0 taken 169881 times.
✗ Branch 1 not taken.
169881 dict_table_stats_lock(ib_table, RW_S_LATCH);
19732 }
19733
19734
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 9310204 times.
9310254 ut_a(ib_table->stat_initialized);
19735
19736 9310204 const dict_index_t *pk = UT_LIST_GET_FIRST(ib_table->indexes);
19737
19738
2/2
✓ Branch 0 taken 23283749 times.
✓ Branch 1 taken 9310547 times.
32594296 for (uint i = 0; i < table->s->keys; i++) {
19739 ulong j;
19740 /* We could get index quickly through internal
19741 index mapping with the index translation table.
19742 The identity of index (match up index name with
19743 that of table->key_info[i]) is already verified in
19744 innobase_get_index(). */
19745
1/2
✓ Branch 0 taken 23284205 times.
✗ Branch 1 not taken.
23283749 dict_index_t *index = innobase_get_index(i);
19746
19747
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23284205 times.
23284205 if (index == nullptr) {
19748 log_errlog(ERROR_LEVEL, ER_INNODB_IDX_CNT_FEWER_THAN_DEFINED_IN_MYSQL,
19749 ib_table->name.m_name, TROUBLESHOOTING_MSG);
19750 break;
19751 }
19752
19753 23284205 KEY *key = &table->key_info[i];
19754
19755 double pct_cached;
19756
19757 /* We do not maintain stats for fulltext or spatial indexes.
19758 Thus, we can't calculate pct_cached below because we need
19759 dict_index_t::stat_n_leaf_pages for that. See
19760 dict_stats_should_ignore_index(). */
19761
4/4
✓ Branch 0 taken 23268726 times.
✓ Branch 1 taken 15479 times.
✓ Branch 2 taken 19679 times.
✓ Branch 3 taken 23249047 times.
23284205 if ((key->flags & HA_FULLTEXT) || (key->flags & HA_SPATIAL)) {
19762 35158 pct_cached = IN_MEMORY_ESTIMATE_UNKNOWN;
19763 } else {
19764
1/2
✓ Branch 0 taken 23248856 times.
✗ Branch 1 not taken.
23249047 pct_cached = index_pct_cached(index);
19765 }
19766
19767 23284014 key->set_in_memory_estimate(pct_cached);
19768
19769
2/2
✓ Branch 0 taken 7770136 times.
✓ Branch 1 taken 15513978 times.
23284114 if (index == pk) {
19770 7770136 stats.table_in_mem_estimate = pct_cached;
19771 }
19772
19773
2/2
✓ Branch 0 taken 10113158 times.
✓ Branch 1 taken 13170956 times.
23284114 if (flag & HA_STATUS_CONST) {
19774
2/2
✓ Branch 0 taken 2732 times.
✓ Branch 1 taken 10110417 times.
10113158 if (!key->supports_records_per_key()) {
19775 2732 continue;
19776 }
19777
19778
2/2
✓ Branch 0 taken 20963346 times.
✓ Branch 1 taken 10110404 times.
31073750 for (j = 0; j < key->actual_key_parts; j++) {
19779
4/4
✓ Branch 0 taken 20958293 times.
✓ Branch 1 taken 5053 times.
✓ Branch 2 taken 1411 times.
✓ Branch 3 taken 20956882 times.
20963346 if ((key->flags & HA_FULLTEXT) || (key->flags & HA_SPATIAL)) {
19780 /* The record per key does not apply to
19781 FTS or Spatial indexes. */
19782 6464 key->set_records_per_key(j, 1.0f);
19783 6470 continue;
19784 }
19785
19786
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20956882 times.
20956882 if (j + 1 > index->n_uniq) {
19787 log_errlog(ERROR_LEVEL, ER_INNODB_IDX_COLUMN_CNT_DIFF, index->name(),
19788 ib_table->name.m_name, (unsigned long)index->n_uniq, j + 1,
19789 TROUBLESHOOTING_MSG);
19790 break;
19791 }
19792
19793 /* innodb_rec_per_key() will use
19794 index->stat_n_diff_key_vals[] and the value we
19795 pass index->table->stat_n_rows. Both are
19796 calculated by ANALYZE and by the background
19797 stats gathering thread (which kicks in when too
19798 much of the table has been changed). In
19799 addition table->stat_n_rows is adjusted with
19800 each DML (e.g. ++ on row insert). Those
19801 adjustments are not MVCC'ed and not even
19802 reversed on rollback. So,
19803 index->stat_n_diff_key_vals[] and
19804 index->table->stat_n_rows could have been
19805 calculated at different time. This is
19806 acceptable. */
19807 const rec_per_key_t rec_per_key =
19808
1/2
✓ Branch 0 taken 20956853 times.
✗ Branch 1 not taken.
20956882 innodb_rec_per_key(index, (ulint)j, index->table->stat_n_rows);
19809
19810 20956853 key->set_records_per_key(j, rec_per_key);
19811
19812 /* The code below is legacy and should be
19813 removed together with this comment once we
19814 are sure the new floating point rec_per_key,
19815 set via set_records_per_key(), works fine. */
19816
19817 ulong rec_per_key_int = static_cast<ulong>(
19818
1/2
✓ Branch 0 taken 20956863 times.
✗ Branch 1 not taken.
20956858 innodb_rec_per_key(index, (ulint)j, stats.records));
19819
19820 /* Since MySQL seems to favor table scans
19821 too much over index searches, we pretend
19822 index selectivity is 2 times better than
19823 our estimate: */
19824
19825 20956863 rec_per_key_int = rec_per_key_int / 2;
19826
19827
2/2
✓ Branch 0 taken 15156052 times.
✓ Branch 1 taken 5800811 times.
20956863 if (rec_per_key_int == 0) {
19828 15156052 rec_per_key_int = 1;
19829 }
19830
19831 20956863 key->rec_per_key[j] = rec_per_key_int;
19832 }
19833 }
19834 }
19835
19836
2/2
✓ Branch 0 taken 169881 times.
✓ Branch 1 taken 9140666 times.
9310547 if (!(flag & HA_STATUS_NO_LOCK)) {
19837
1/2
✓ Branch 0 taken 169690 times.
✗ Branch 1 not taken.
169881 dict_table_stats_unlock(ib_table, RW_S_LATCH);
19838 }
19839
19840
2/2
✓ Branch 0 taken 1736 times.
✓ Branch 1 taken 9308620 times.
9310356 if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
19841 1736 goto func_exit;
19842
19843
2/2
✓ Branch 0 taken 914424 times.
✓ Branch 1 taken 8394196 times.
9308620 } else if (flag & HA_STATUS_ERRKEY) {
19844 const dict_index_t *err_index;
19845
19846
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 914424 times.
914424 ut_a(m_prebuilt->trx);
19847
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 914424 times.
914424 ut_a(m_prebuilt->trx->magic_n == TRX_MAGIC_N);
19848
19849 914424 err_index = trx_get_error_index(m_prebuilt->trx);
19850
19851
2/2
✓ Branch 0 taken 914422 times.
✓ Branch 1 taken 2 times.
914424 if (err_index) {
19852
1/2
✓ Branch 0 taken 914422 times.
✗ Branch 1 not taken.
914422 errkey = innobase_get_mysql_key_number_for_index(m_share, table, ib_table,
19853 err_index);
19854 } else {
19855 2 errkey =
19856 (unsigned int)((m_prebuilt->trx->error_key_num == ULINT_UNDEFINED)
19857 ? ~0
19858 2 : m_prebuilt->trx->error_key_num);
19859 }
19860 }
19861
19862
4/4
✓ Branch 0 taken 9158874 times.
✓ Branch 1 taken 149746 times.
✓ Branch 2 taken 135542 times.
✓ Branch 3 taken 14204 times.
9308620 if ((flag & HA_STATUS_AUTO) && table->found_next_number_field) {
19863
1/2
✓ Branch 0 taken 14204 times.
✗ Branch 1 not taken.
14204 ulonglong auto_inc_val = innobase_peek_autoinc(ib_table, true);
19864 /* Initialize autoinc value if not set. */
19865
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14204 times.
14204 if (auto_inc_val == 0) {
19866 dict_table_autoinc_lock(m_prebuilt->table);
19867 innobase_initialize_autoinc();
19868 dict_table_autoinc_unlock(m_prebuilt->table);
19869
19870 auto_inc_val = innobase_peek_autoinc(ib_table, true);
19871 }
19872 14204 stats.auto_increment_value = auto_inc_val;
19873 }
19874
19875 9294416 func_exit:
19876 9310356 m_prebuilt->trx->op_info = (char *)"";
19877
19878 9310356 return 0;
19879 9310356 }
19880
19881 /** Returns statistics information of the table to the MySQL interpreter,
19882 in various fields of the handle object.
19883 @return HA_ERR_* error code or 0 */
19884
19885 9572626 int ha_innobase::info(uint flag) /*!< in: what information is requested */
19886 {
19887 9572626 return (info_low(flag, false /* not ANALYZE */));
19888 }
19889
19890 /** Get the autoincrement for the given table id which is
19891 not in the cache.
19892 @param[in] se_private_id InnoDB table id
19893 @param[in] tbl_se_private_data table SE private data
19894 @return autoincrement value for the given table_id. */
19895 14 static uint64_t innodb_get_auto_increment_for_uncached(
19896 dd::Object_id se_private_id, const dd::Properties &tbl_se_private_data) {
19897 14 uint64_t autoinc = 0;
19898 14 uint64_t meta_autoinc = 0;
19899
19900 bool exists =
19901
2/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
14 tbl_se_private_data.exists(dd_table_key_strings[DD_TABLE_AUTOINC]);
19902
19903 /** Get the auto_increment from the table SE private data. */
19904
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (exists) {
19905 tbl_se_private_data.get(dd_table_key_strings[DD_TABLE_AUTOINC], &autoinc);
19906 }
19907
19908 /** Get the auto_increment value from innodb_dynamic_metadata
19909 table. */
19910
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 mutex_enter(&dict_persist->mutex);
19911
19912 14 DDTableBuffer *table_buffer = dict_persist->table_buffer;
19913
19914 uint64_t version;
19915
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 std::string *readmeta = table_buffer->get(se_private_id, &version);
19916
19917
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (readmeta->length() != 0) {
19918 PersistentTableMetadata metadata(se_private_id, version);
19919
19920 dict_table_read_dynamic_metadata(
19921 reinterpret_cast<const byte *>(readmeta->data()), readmeta->length(),
19922 &metadata);
19923
19924 meta_autoinc = metadata.get_autoinc();
19925 }
19926
19927
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 mutex_exit(&dict_persist->mutex);
19928
19929 14 ut::delete_(readmeta);
19930
19931 14 return (std::max(meta_autoinc, autoinc));
19932 }
19933
19934 /** Retrieves table statistics only for uncache table only.
19935 @param[in] db_name database name
19936 @param[in] tbl_name table name
19937 @param[in] norm_name tablespace name
19938 @param[in] se_private_id InnoDB table id
19939 @param[in] ts_se_private_data tablespace se private data
19940 @param[in] tbl_se_private_data table se private data
19941 @param[in] stat_flags flags used to retrieve specific stats
19942 @param[in,out] stats structure to save the retrieved statistics
19943 @return true if the stats information filled successfully
19944 @return false if tablespace is missing or table doesn't have persistent
19945 stats. */
19946 23 static bool innodb_get_table_statistics_for_uncached(
19947 const char *db_name, const char *tbl_name, const char *norm_name,
19948 dd::Object_id se_private_id, const dd::Properties &ts_se_private_data,
19949 const dd::Properties &tbl_se_private_data, ulint stat_flags,
19950 ha_statistics *stats) {
19951
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 TableStatsRecord stat_info;
19952 space_id_t space_id;
19953
19954
3/4
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 14 times.
23 if (!row_search_table_stats(db_name, tbl_name, stat_info)) {
19955 9 return (false);
19956 }
19957
19958 /** Server passes dummy ts_se_private_data for file_per_table
19959 tablespace. In that case, InnoDB should find the space_id using
19960 the tablespace name. */
19961
2/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
14 bool exists = ts_se_private_data.exists(dd_space_key_strings[DD_SPACE_ID]);
19962
19963
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (exists) {
19964 ts_se_private_data.get(dd_space_key_strings[DD_SPACE_ID], &space_id);
19965 } else {
19966
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 space_id = fil_space_get_id_by_name(norm_name);
19967
19968
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (space_id == SPACE_UNKNOWN) {
19969 return (false);
19970 }
19971 }
19972
19973 fil_space_t *space;
19974 uint32_t fsp_flags;
19975
19976
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 space = fil_space_acquire(space_id);
19977
19978 /** Tablespace is missing in this case. */
19979
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (space == nullptr) {
19980 return (false);
19981 }
19982
19983 14 fsp_flags = space->flags;
19984
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 page_size_t page_size(fsp_flags);
19985
19986
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 if (stat_flags & HA_STATUS_VARIABLE_EXTRA) {
19987
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 ulint avail_space = fsp_get_available_space_in_free_extents(space);
19988 14 stats->delete_length = avail_space * 1024;
19989 }
19990
19991
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 fil_space_release(space);
19992
19993
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 if (stat_flags & HA_STATUS_AUTO) {
19994
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 stats->auto_increment_value = innodb_get_auto_increment_for_uncached(
19995 se_private_id, tbl_se_private_data);
19996 }
19997
19998
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 if (stat_flags & HA_STATUS_TIME) {
19999 14 stats->update_time = (time_t)NULL;
20000 }
20001
20002
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 if (stat_flags & HA_STATUS_VARIABLE) {
20003
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 stats->records = static_cast<ha_rows>(stat_info.get_n_rows());
20004 14 stats->data_file_length =
20005
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 static_cast<ulonglong>(stat_info.get_clustered_index_size()) *
20006
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 page_size.physical();
20007 14 stats->index_file_length =
20008
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 static_cast<ulonglong>(stat_info.get_sum_of_other_index_size()) *
20009
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 page_size.physical();
20010
20011
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8 times.
14 if (stats->records == 0) {
20012 6 stats->mean_rec_length = 0;
20013 } else {
20014 8 stats->mean_rec_length =
20015 8 static_cast<ulong>(stats->data_file_length / stats->records);
20016 }
20017 }
20018
20019 14 return (true);
20020 23 }
20021
20022 3459 static bool innobase_get_table_statistics(
20023 const char *db_name, const char *table_name, dd::Object_id se_private_id,
20024 const dd::Properties &ts_se_private_data,
20025 const dd::Properties &tbl_se_private_data, uint stat_flags,
20026 ha_statistics *stats) {
20027 char norm_name[FN_REFLEN];
20028 dict_table_t *ib_table;
20029
20030 char buf[2 * NAME_CHAR_LEN * 5 + 2 + 1];
20031 bool truncated;
20032
1/2
✓ Branch 0 taken 3459 times.
✗ Branch 1 not taken.
3459 build_table_filename(buf, sizeof(buf), db_name, table_name, nullptr, 0,
20033 &truncated);
20034
20035
4/8
✓ Branch 0 taken 3459 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3459 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3459 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3459 times.
3459 if (truncated || !normalize_table_name(norm_name, buf)) {
20036 ut_d(ut_error);
20037 ut_o(return true); // (HA_ERR_TOO_LONG_PATH);
20038 }
20039
20040 3459 MDL_ticket *mdl = nullptr;
20041
1/2
✓ Branch 0 taken 3459 times.
✗ Branch 1 not taken.
3459 THD *thd = current_thd;
20042
20043
1/2
✓ Branch 0 taken 3459 times.
✗ Branch 1 not taken.
3459 ib_table = dd_table_open_on_name_in_mem(norm_name, false);
20044
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 3436 times.
3459 if (ib_table == nullptr) {
20045
3/4
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 9 times.
23 if (innodb_get_table_statistics_for_uncached(
20046 db_name, table_name, norm_name, se_private_id, ts_se_private_data,
20047 tbl_se_private_data, stat_flags, stats)) {
20048 14 return (false);
20049 }
20050
20051 /** If the table doesn't have persistent stats then
20052 load the table from disk. */
20053
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 ib_table = dd_table_open_on_name(thd, &mdl, norm_name, false,
20054 DICT_ERR_IGNORE_NONE);
20055
20056
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ib_table == nullptr) {
20057 return (true);
20058 }
20059 }
20060
20061
1/2
✓ Branch 0 taken 3445 times.
✗ Branch 1 not taken.
3445 if (stat_flags & HA_STATUS_AUTO) {
20062
1/2
✓ Branch 0 taken 3445 times.
✗ Branch 1 not taken.
3445 stats->auto_increment_value = innobase_peek_autoinc(ib_table, false);
20063 }
20064
20065
1/2
✓ Branch 0 taken 3445 times.
✗ Branch 1 not taken.
3445 if (stat_flags & HA_STATUS_TIME) {
20066 3445 stats->update_time = static_cast<ulong>(
20067 3445 std::chrono::system_clock::to_time_t(ib_table->update_time.load()));
20068 }
20069
20070
1/2
✓ Branch 0 taken 3445 times.
✗ Branch 1 not taken.
3445 if (stat_flags & HA_STATUS_VARIABLE_EXTRA) {
20071
2/4
✓ Branch 0 taken 3445 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3445 times.
✗ Branch 3 not taken.
3445 calculate_delete_length_stat(ib_table, stats, current_thd);
20072 }
20073
20074
1/2
✓ Branch 0 taken 3445 times.
✗ Branch 1 not taken.
3445 if (stat_flags & HA_STATUS_VARIABLE) {
20075
1/2
✓ Branch 0 taken 3445 times.
✗ Branch 1 not taken.
3445 dict_stats_init(ib_table);
20076
20077
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3445 times.
3445 ut_a(ib_table->stat_initialized);
20078
20079 /* Note it may look like ib_table->* arguments are
20080 redundant. If you see the usage of this call in info_low(),
20081 the stats can be retrieved while holding a latch if
20082 !HA_STATUS_NO_LOCK is passed. */
20083
1/2
✓ Branch 0 taken 3445 times.
✗ Branch 1 not taken.
3445 calculate_index_size_stats(ib_table, ib_table->stat_n_rows,
20084 ib_table->stat_clustered_index_size,
20085 ib_table->stat_sum_of_other_index_sizes, stats);
20086 }
20087
20088
1/2
✓ Branch 0 taken 3445 times.
✗ Branch 1 not taken.
3445 dd_table_close(ib_table, thd, &mdl, false);
20089
20090 3445 return (false);
20091 }
20092
20093 768 static bool innobase_get_index_column_cardinality(
20094 const char *db_name, const char *table_name, const char *index_name, uint,
20095 uint column_ordinal_position, dd::Object_id, ulonglong *cardinality) {
20096 char norm_name[FN_REFLEN];
20097 dict_table_t *ib_table;
20098 768 bool failure = true;
20099
20100 char buf[2 * NAME_CHAR_LEN * 5 + 2 + 1];
20101 bool truncated;
20102
1/2
✓ Branch 0 taken 768 times.
✗ Branch 1 not taken.
768 build_table_filename(buf, sizeof(buf), db_name, table_name, nullptr, 0,
20103 &truncated);
20104
20105
4/8
✓ Branch 0 taken 768 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 768 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 768 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 768 times.
768 if (truncated || !normalize_table_name(norm_name, buf)) {
20106 /* purecov: begin inspected */
20107 ut_d(ut_error);
20108 ut_o(return (true));
20109 /* purecov: end */
20110 }
20111
20112 768 MDL_ticket *mdl = nullptr;
20113
1/2
✓ Branch 0 taken 768 times.
✗ Branch 1 not taken.
768 THD *thd = current_thd;
20114
20115
1/2
✓ Branch 0 taken 768 times.
✗ Branch 1 not taken.
768 ib_table = dd_table_open_on_name_in_mem(norm_name, false);
20116
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 767 times.
768 if (ib_table == nullptr) {
20117
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if (row_search_index_stats(db_name, table_name, index_name,
20118 column_ordinal_position, cardinality)) {
20119 1 return (false);
20120 }
20121
20122 /** If the table doesn't have persistent stats then
20123 load the table from disk. */
20124 ib_table = dd_table_open_on_name(thd, &mdl, norm_name, false,
20125 DICT_ERR_IGNORE_NONE);
20126
20127 if (ib_table == nullptr) {
20128 return (true);
20129 }
20130 }
20131
20132
2/4
✓ Branch 0 taken 767 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 767 times.
767 if (ib_table->is_fts_aux()) {
20133 /* Server should not ask for Stats for Internal Tables */
20134 dd_table_close(ib_table, thd, &mdl, false);
20135 ut_d(ut_error);
20136 ut_o(return (true));
20137 }
20138
20139
5/10
✓ Branch 0 taken 767 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 767 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 281 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1048 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1048 times.
✗ Branch 9 not taken.
1048 for (const dict_index_t *index : ib_table->indexes) {
20140
6/8
✓ Branch 0 taken 1048 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1048 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 767 times.
✓ Branch 5 taken 281 times.
✓ Branch 6 taken 767 times.
✓ Branch 7 taken 281 times.
1048 if (index->is_committed() && ut_strcmp(index_name, index->name) == 0) {
20141
2/2
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 698 times.
767 if (ib_table->stat_initialized == 0) {
20142
1/2
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
69 dict_stats_init(ib_table);
20143
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
69 ut_a(ib_table->stat_initialized != 0);
20144 }
20145
20146
2/4
✓ Branch 0 taken 767 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 767 times.
✗ Branch 3 not taken.
767 DEBUG_SYNC(thd, "innodb.after_init_check");
20147
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 749 times.
767 if (index->type & (DICT_FTS | DICT_SPATIAL)) {
20148 /* For these indexes innodb_rec_per_key is
20149 fixed as 1.0 */
20150 18 *cardinality = ib_table->stat_n_rows;
20151 } else {
20152 749 uint64_t n_rows = ib_table->stat_n_rows;
20153 double records =
20154 1498 (n_rows /
20155
1/2
✓ Branch 0 taken 749 times.
✗ Branch 1 not taken.
749 innodb_rec_per_key(index, (ulint)column_ordinal_position, n_rows));
20156 749 *cardinality = static_cast<ulonglong>(round(records));
20157 }
20158
20159 767 failure = false;
20160 767 break;
20161 }
20162 }
20163
20164
1/2
✓ Branch 0 taken 767 times.
✗ Branch 1 not taken.
767 dd_table_close(ib_table, thd, &mdl, false);
20165 767 return (failure);
20166 }
20167
20168 966 static bool innobase_is_tablespace_keyring_pre_v3_encrypted(
20169 const dd::Tablespace &tablespace, int &error) {
20170 966 error = 0;
20171 966 space_id_t id = 0;
20172
20173
3/6
✓ Branch 0 taken 966 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 966 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 966 times.
966 ut_ad(innobase_strcasecmp(tablespace.engine().c_str(), "InnoDB") == 0);
20174
20175
4/8
✓ Branch 0 taken 966 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 966 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 966 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 966 times.
966 if (tablespace.se_private_data().get(dd_space_key_strings[DD_SPACE_ID], &id))
20176 return true;
20177
20178 /* Make sure tablespace is loaded. */
20179
1/2
✓ Branch 0 taken 966 times.
✗ Branch 1 not taken.
966 fil_space_t *space = fil_space_get(id);
20180
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 957 times.
966 if (space == nullptr) {
20181 9 error = HA_ERR_TABLESPACE_MISSING;
20182 9 return false;
20183 }
20184
20185 // If page0 was read and it has crypt - we can check if it is encrypted here
20186 // if crypt_data is null it means that page0 may not have yet been read - we
20187 // will read it in fil_space_open_if_needed and recheck if crypt_data is null
20188
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 957 times.
957 if (space->crypt_data != nullptr)
20189 return is_space_keyring_pre_v3_encrypted(space);
20190
20191
1/2
✓ Branch 0 taken 957 times.
✗ Branch 1 not taken.
957 fil_space_open_if_needed(space);
20192
20193 // We do not need to care about mutexes as this function is only called during
20194 // the upgrade
20195
1/2
✓ Branch 0 taken 957 times.
✗ Branch 1 not taken.
957 return is_space_keyring_pre_v3_encrypted(space);
20196 }
20197
20198 407974 static bool innobase_get_tablespace_type(const dd::Tablespace &space,
20199 Tablespace_type *space_type) {
20200 407974 space_id_t id = 0;
20201 407974 uint32_t flags = 0;
20202
20203
3/6
✓ Branch 0 taken 407974 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 407974 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 407974 times.
407974 ut_ad(innobase_strcasecmp(space.engine().c_str(), "InnoDB") == 0);
20204
20205
5/12
✓ Branch 0 taken 407974 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 407974 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 407974 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 407974 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 407974 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
1223922 if (space.se_private_data().get(dd_space_key_strings[DD_SPACE_ID], &id) ||
20206
6/14
✓ Branch 0 taken 407974 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 407974 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 407974 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 407974 times.
✓ Branch 8 taken 407974 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 407974 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
815948 space.se_private_data().get(dd_space_key_strings[DD_SPACE_FLAGS],
20207 &flags)) {
20208 return true;
20209 }
20210
20211
5/6
✓ Branch 0 taken 407974 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 65967 times.
✓ Branch 3 taken 342007 times.
✓ Branch 4 taken 65967 times.
✓ Branch 5 taken 342007 times.
473941 if (space.id() == MYSQL_TABLESPACE_DD_ID &&
20212
1/2
✓ Branch 0 taken 65967 times.
✗ Branch 1 not taken.
65967 id == dict_sys_t::s_dict_space_id) {
20213 65967 *space_type = Tablespace_type::SPACE_TYPE_DICTIONARY;
20214
2/2
✓ Branch 0 taken 681 times.
✓ Branch 1 taken 341326 times.
342007 } else if (id == TRX_SYS_SPACE) {
20215 681 *space_type = Tablespace_type::SPACE_TYPE_SYSTEM;
20216
3/4
✓ Branch 0 taken 341326 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
✓ Branch 3 taken 341295 times.
341326 } else if (fsp_is_undo_tablespace(id)) {
20217 31 *space_type = Tablespace_type::SPACE_TYPE_UNDO;
20218
3/4
✓ Branch 0 taken 341295 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 341280 times.
341295 } else if (fsp_is_system_temporary(id)) {
20219 15 *space_type = Tablespace_type::SPACE_TYPE_TEMPORARY;
20220
6/8
✓ Branch 0 taken 330976 times.
✓ Branch 1 taken 10304 times.
✓ Branch 2 taken 330976 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 330976 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 330976 times.
✓ Branch 7 taken 10304 times.
341280 } else if (fsp_is_shared_tablespace(flags) && fsp_is_ibd_tablespace(id)) {
20221 330976 *space_type = Tablespace_type::SPACE_TYPE_SHARED;
20222
2/4
✓ Branch 0 taken 10304 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10304 times.
✗ Branch 3 not taken.
10304 } else if (fsp_is_file_per_table(id, flags)) {
20223 10304 *space_type = Tablespace_type::SPACE_TYPE_IMPLICIT;
20224 } else {
20225 ut_d(ut_error);
20226 ut_o(return true);
20227 }
20228
20229 407974 return false;
20230 }
20231
20232 /** Get the tablespace type given the name.
20233
20234 @param[in] tablespace_name tablespace name
20235 @param[out] space_type type of space
20236
20237 @return Operation status.
20238 @retval false on success and true for failure.
20239 */
20240 1138942 static bool innobase_get_tablespace_type_by_name(const char *tablespace_name,
20241 Tablespace_type *space_type) {
20242
6/6
✓ Branch 0 taken 373991 times.
✓ Branch 1 taken 764951 times.
✓ Branch 2 taken 924 times.
✓ Branch 3 taken 373067 times.
✓ Branch 4 taken 764952 times.
✓ Branch 5 taken 923 times.
1138942 if ((tablespace_name == nullptr && srv_file_per_table) ||
20243 764952 (tablespace_name &&
20244
2/2
✓ Branch 0 taken 1183 times.
✓ Branch 1 taken 763769 times.
764952 0 == strcmp(tablespace_name, dict_sys_t::s_file_per_table_name))) {
20245 374250 *space_type = Tablespace_type::SPACE_TYPE_IMPLICIT;
20246
4/6
✓ Branch 0 taken 924 times.
✓ Branch 1 taken 763768 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 924 times.
✓ Branch 4 taken 763770 times.
✗ Branch 5 not taken.
764692 } else if ((tablespace_name == nullptr && !srv_file_per_table) ||
20247 763770 (tablespace_name &&
20248
2/2
✓ Branch 0 taken 1009 times.
✓ Branch 1 taken 762761 times.
763770 0 == strcmp(tablespace_name, dict_sys_t::s_sys_space_name))) {
20249 1933 *space_type = Tablespace_type::SPACE_TYPE_SYSTEM;
20250
2/2
✓ Branch 0 taken 759477 times.
✓ Branch 1 taken 3282 times.
762759 } else if (0 == strcmp(tablespace_name, dict_sys_t::s_dd_space_name)) {
20251 759477 *space_type = Tablespace_type::SPACE_TYPE_DICTIONARY;
20252
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3274 times.
3282 } else if (0 == strcmp(tablespace_name, dict_sys_t::s_temp_space_name)) {
20253 8 *space_type = Tablespace_type::SPACE_TYPE_TEMPORARY;
20254
1/2
✓ Branch 0 taken 3276 times.
✗ Branch 1 not taken.
3274 } else if (0 == strcmp(tablespace_name,
20255 3276 dict_sys_t::s_default_undo_space_name_1) ||
20256
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3276 times.
3276 0 == strcmp(tablespace_name,
20257 dict_sys_t::s_default_undo_space_name_2)) {
20258 /*
20259 TODO: This function doesn't consider user created UNDO
20260 tablespaces because, as of now this function is not being
20261 called for UNDO tablesapces. But should consider this in
20262 future for completeness.
20263 */
20264 *space_type = Tablespace_type::SPACE_TYPE_UNDO;
20265 } else {
20266 3276 *space_type = Tablespace_type::SPACE_TYPE_SHARED;
20267 }
20268
20269 1138942 return false;
20270 }
20271
20272 251509 static bool innobase_get_tablespace_statistics(
20273 const char *tablespace_name, const char *file_name,
20274 const dd::Properties &ts_se_private_data, ha_tablespace_statistics *stats) {
20275 /* Tablespace does not have space id stored. */
20276
3/6
✓ Branch 0 taken 251509 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 251509 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 251509 times.
251509 if (!ts_se_private_data.exists(dd_space_key_strings[DD_SPACE_ID])) {
20277 my_error(ER_TABLESPACE_MISSING, MYF(0), tablespace_name);
20278 return (DD_FAILURE);
20279 }
20280
20281 space_id_t space_id;
20282
20283
2/4
✓ Branch 0 taken 251509 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 251509 times.
✗ Branch 3 not taken.
251509 ts_se_private_data.get(dd_space_key_strings[DD_SPACE_ID], &space_id);
20284
20285
3/4
✓ Branch 0 taken 251509 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50486 times.
✓ Branch 3 taken 201023 times.
251509 if (fsp_is_undo_tablespace(space_id)) {
20286 /* Get the ddl_mutex so that if an undo truncation is happening by
20287 the purge thread, it will complete before we continue. */
20288
1/2
✓ Branch 0 taken 50486 times.
✗ Branch 1 not taken.
50486 mutex_enter(&undo::ddl_mutex);
20289
20290 /* When selecting information_schema.files, no MVCC is used. So it is
20291 possible to read an uncommitted DD record that indicates the undo
20292 space is empty and shows the new space_id after a truncation.
20293 Adjust for that possibility by always using the current space_id. */
20294
1/2
✓ Branch 0 taken 50486 times.
✗ Branch 1 not taken.
50486 undo::spaces->s_lock();
20295 50486 space_id_t undo_num = undo::id2num(space_id);
20296
1/2
✓ Branch 0 taken 50486 times.
✗ Branch 1 not taken.
50486 undo::Tablespace *undo_space = undo::spaces->find(undo_num);
20297
2/2
✓ Branch 0 taken 50479 times.
✓ Branch 1 taken 7 times.
50486 if (undo_space != nullptr) {
20298 50479 space_id = undo_space->id();
20299 }
20300
1/2
✓ Branch 0 taken 50486 times.
✗ Branch 1 not taken.
50486 undo::spaces->s_unlock();
20301 }
20302
20303
1/2
✓ Branch 0 taken 251509 times.
✗ Branch 1 not taken.
251509 auto space = fil_space_acquire(space_id);
20304
20305 /* Tablespace is missing in this case. */
20306
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 251470 times.
251509 if (space == nullptr) {
20307
1/2
✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
39 my_error(ER_TABLESPACE_MISSING, MYF(0), tablespace_name);
20308
3/4
✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 32 times.
39 if (fsp_is_undo_tablespace(space_id)) {
20309
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 mutex_exit(&undo::ddl_mutex);
20310 }
20311 39 return (DD_FAILURE);
20312 }
20313
20314 251470 stats->m_id = space->id;
20315
20316 251470 const char *type = "TABLESPACE";
20317
20318 251470 fil_type_t purpose = space->purpose;
20319
20320
2/4
✓ Branch 0 taken 226499 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24971 times.
✗ Branch 3 not taken.
251470 switch (purpose) {
20321 226499 case FIL_TYPE_TABLESPACE:
20322
3/4
✓ Branch 0 taken 226499 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50479 times.
✓ Branch 3 taken 176020 times.
226499 if (fsp_is_undo_tablespace(space_id)) {
20323 50479 type = "UNDO LOG";
20324 50479 break;
20325 } /* else fall through for TABLESPACE */
20326 case FIL_TYPE_IMPORT:
20327 /* 'IMPORTING'is a status. The type is TABLESPACE. */
20328 176020 break;
20329 24971 case FIL_TYPE_TEMPORARY:
20330 24971 type = "TEMPORARY";
20331 24971 break;
20332 }
20333
20334
1/2
✓ Branch 0 taken 251470 times.
✗ Branch 1 not taken.
251470 stats->m_type = type;
20335
20336 251470 stats->m_free_extents = space->free_len;
20337
20338
1/2
✓ Branch 0 taken 251470 times.
✗ Branch 1 not taken.
251470 page_size_t page_size{space->flags};
20339
20340
1/2
✓ Branch 0 taken 251470 times.
✗ Branch 1 not taken.
251470 page_no_t extent_pages = fsp_get_extent_size_in_pages(page_size);
20341
20342 251470 stats->m_total_extents = space->size_in_header / extent_pages;
20343
20344
1/2
✓ Branch 0 taken 251470 times.
✗ Branch 1 not taken.
251470 stats->m_extent_size = extent_pages * page_size.physical();
20345
20346 251470 const fil_node_t *file = nullptr;
20347
20348 /* Use only the basename when searching for system tablespaces since
20349 InnoDB places them in innodb_data_home_dir and the DD may only know
20350 the basename. Since they are open, they are in the right place. */
20351 std::string search_name =
20352
2/2
✓ Branch 0 taken 24971 times.
✓ Branch 1 taken 201515 times.
226486 (space->id == TRX_SYS_SPACE || space->id == dict_sys_t::s_temp_space_id)
20353 251470 ? Fil_path::get_basename(file_name)
20354
11/20
✓ Branch 0 taken 226486 times.
✓ Branch 1 taken 24984 times.
✓ Branch 2 taken 49955 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 49955 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 201515 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 201515 times.
✓ Branch 9 taken 49955 times.
✓ Branch 10 taken 49955 times.
✓ Branch 11 taken 201515 times.
✓ Branch 12 taken 49955 times.
✓ Branch 13 taken 201515 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
1030851 : file_name;
20355
20356 /* Normalize the file name to search for. */
20357 251470 Fil_path::normalize(search_name);
20358
20359 /* Find the fil_node_t that matches the filename. */
20360
1/2
✓ Branch 0 taken 251487 times.
✗ Branch 1 not taken.
251487 for (const auto &f : space->files) {
20361
4/6
✓ Branch 0 taken 251487 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 251487 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 251463 times.
✓ Branch 5 taken 24 times.
251487 if (Fil_path::is_same_as(search_name, f.name)) {
20362 251463 file = &f;
20363 251463 break;
20364 }
20365
20366 /* Try to compare only the basename. */
20367
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 21 times.
24 if (space->id == TRX_SYS_SPACE ||
20368
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 space->id == dict_sys_t::s_temp_space_id) {
20369
5/8
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 7 times.
✓ Branch 7 taken 17 times.
24 if (Fil_path::is_same_as(search_name, Fil_path::get_basename(f.name))) {
20370 7 file = &f;
20371 7 break;
20372 }
20373 }
20374
20375
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (space->files.size() == 1) {
20376 file = &f;
20377
20378 ib::info(ER_IB_MSG_570)
20379 << "Tablespace '" << tablespace_name << "'with DD filename '"
20380 << file_name << "' doesn't match the InnoDB filename '" << f.name
20381 << "'";
20382 }
20383 }
20384
20385
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 251470 times.
251470 if (file == nullptr) {
20386 ib::warn(ER_IB_MSG_571) << "Tablespace '" << tablespace_name << "'"
20387 << " filename is unknown. Use --innodb-directories"
20388 << " to tell InnoDB the location of the file.";
20389
20390 my_error(ER_TABLESPACE_MISSING, MYF(0), tablespace_name);
20391
20392 if (fsp_is_undo_tablespace(space_id)) {
20393 mutex_exit(&undo::ddl_mutex);
20394 }
20395
20396 return (DD_FAILURE);
20397 }
20398
20399
1/2
✓ Branch 0 taken 251470 times.
✗ Branch 1 not taken.
251470 stats->m_initial_size = file->init_size * page_size.physical();
20400
20401 /** Store maximum size */
20402
2/2
✓ Branch 0 taken 251457 times.
✓ Branch 1 taken 13 times.
251470 if (file->max_size >= PAGE_NO_MAX) {
20403 251457 stats->m_maximum_size = ~0ULL;
20404 } else {
20405
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 stats->m_maximum_size = file->max_size * page_size.physical();
20406 }
20407
20408 /** Store autoextend size */
20409 page_no_t extend_pages;
20410
20411
2/2
✓ Branch 0 taken 24984 times.
✓ Branch 1 taken 226486 times.
251470 if (space->id == TRX_SYS_SPACE) {
20412
1/2
✓ Branch 0 taken 24984 times.
✗ Branch 1 not taken.
24984 extend_pages = srv_sys_space.get_increment();
20413
20414
3/4
✓ Branch 0 taken 226486 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24971 times.
✓ Branch 3 taken 201515 times.
226486 } else if (fsp_is_system_temporary(space->id)) {
20415
1/2
✓ Branch 0 taken 24971 times.
✗ Branch 1 not taken.
24971 extend_pages = srv_tmp_space.get_increment();
20416
20417
3/4
✓ Branch 0 taken 201515 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50479 times.
✓ Branch 3 taken 151036 times.
201515 } else if (fsp_is_undo_tablespace(space->id)) {
20418 50479 extend_pages = space->m_undo_extend;
20419
20420
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 151036 times.
151036 } else if (space->autoextend_size_in_bytes > 0) {
20421 extend_pages = space->autoextend_size_in_bytes / page_size.physical();
20422 } else {
20423
1/2
✓ Branch 0 taken 151036 times.
✗ Branch 1 not taken.
151036 extend_pages = fsp_get_pages_to_extend_ibd(page_size, file->size);
20424 }
20425
20426
1/2
✓ Branch 0 taken 251470 times.
✗ Branch 1 not taken.
251470 stats->m_autoextend_size = extend_pages * page_size.physical();
20427
20428
1/2
✓ Branch 0 taken 251470 times.
✗ Branch 1 not taken.
251470 auto avail_space = fsp_get_available_space_in_free_extents(space);
20429
20430 251470 stats->m_data_free = avail_space * 1024;
20431
20432
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 251470 times.
✓ Branch 2 taken 251470 times.
✗ Branch 3 not taken.
251470 stats->m_status = (purpose == FIL_TYPE_IMPORT ? "IMPORTING" : "NORMAL");
20433
20434
1/2
✓ Branch 0 taken 251470 times.
✗ Branch 1 not taken.
251470 fil_space_release(space);
20435
20436
3/4
✓ Branch 0 taken 251470 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50479 times.
✓ Branch 3 taken 200991 times.
251470 if (fsp_is_undo_tablespace(space_id)) {
20437
1/2
✓ Branch 0 taken 50479 times.
✗ Branch 1 not taken.
50479 mutex_exit(&undo::ddl_mutex);
20438 }
20439
20440 251470 return (DD_SUCCESS);
20441 }
20442
20443 /** Enable indexes.
20444 @param[in] mode enable index mode.
20445 @return HA_ERR_* error code or 0 */
20446 525 int ha_innobase::enable_indexes(uint mode) {
20447 525 int error = HA_ERR_WRONG_COMMAND;
20448
20449 /* Enable index only for intrinsic table. Behavior for all other
20450 table continue to remain same. */
20451
20452
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 525 times.
525 if (m_prebuilt->table->is_intrinsic()) {
20453 ut_ad(mode == HA_KEY_SWITCH_ALL);
20454 for (auto index : m_prebuilt->table->indexes) {
20455 /* InnoDB being clustered index we can't disable/enable
20456 clustered index itself. */
20457 if (index->is_clustered()) {
20458 continue;
20459 }
20460
20461 index->allow_duplicates = false;
20462 }
20463 error = 0;
20464 }
20465
20466 525 return (error);
20467 }
20468
20469 /** Disable indexes.
20470 @param[in] mode disable index mode.
20471 @return HA_ERR_* error code or 0 */
20472 546 int ha_innobase::disable_indexes(uint mode) {
20473 546 int error = HA_ERR_WRONG_COMMAND;
20474
20475 /* Disable index only for intrinsic table. Behavior for all other
20476 table continue to remain same. */
20477
20478
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 546 times.
546 if (m_prebuilt->table->is_intrinsic()) {
20479 ut_ad(mode == HA_KEY_SWITCH_ALL);
20480 for (auto index : m_prebuilt->table->indexes) {
20481 /* InnoDB being clustered index we can't disable/enable
20482 clustered index itself. */
20483 if (index->is_clustered()) {
20484 continue;
20485 }
20486
20487 index->allow_duplicates = true;
20488 }
20489 error = 0;
20490 }
20491
20492 546 return (error);
20493 }
20494
20495 /**
20496 Updates index cardinalities of the table, based on random dives into
20497 each index tree. This does NOT calculate exact statistics on the table.
20498 @return HA_ADMIN_* error code or HA_ADMIN_OK */
20499
20500 13806 int ha_innobase::analyze(THD *, /*!< in: connection thread handle */
20501 HA_CHECK_OPT *) /*!< in: currently ignored */
20502 {
20503
5/10
✓ Branch 0 taken 12373 times.
✓ Branch 1 taken 1433 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12373 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 13806 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 13806 times.
13806 if (UNIV_UNLIKELY(m_share && m_share->ib_table &&
20504 m_share->ib_table->is_corrupt)) {
20505 return (HA_ADMIN_CORRUPT);
20506 }
20507
20508 /* Simply call info_low() with all the flags
20509 and request recalculation of the statistics */
20510 13806 int ret = info_low(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE,
20511 true /* this is ANALYZE */);
20512
20513
5/10
✓ Branch 0 taken 12373 times.
✓ Branch 1 taken 1433 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12373 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 13806 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 13806 times.
13806 if (UNIV_UNLIKELY(m_share && m_share->ib_table &&
20514 m_share->ib_table->is_corrupt)) {
20515 return (HA_ADMIN_CORRUPT);
20516 }
20517
20518
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 13801 times.
13806 if (ret != 0) {
20519 5 return (HA_ADMIN_FAILED);
20520 }
20521
20522 13801 return (HA_ADMIN_OK);
20523 }
20524
20525 /** This is mapped to "ALTER TABLE tablename ENGINE=InnoDB", which rebuilds
20526 the table in MySQL. */
20527
20528 2078 int ha_innobase::optimize(THD *, /*!< in: connection thread handle */
20529 HA_CHECK_OPT *) /*!< in: currently ignored */
20530 {
20531
1/2
✓ Branch 0 taken 2078 times.
✗ Branch 1 not taken.
2078 TrxInInnoDB trx_in_innodb(m_prebuilt->trx);
20532
20533 /* FTS-FIXME: Since MySQL doesn't support engine-specific commands,
20534 we have to hijack some existing command in order to be able to test
20535 the new admin commands added in InnoDB's FTS support. For now, we
20536 use MySQL's OPTIMIZE command, normally mapped to ALTER TABLE in
20537 InnoDB (so it recreates the table anew), and map it to OPTIMIZE.
20538
20539 This works OK otherwise, but MySQL locks the entire table during
20540 calls to OPTIMIZE, which is undesirable. */
20541
20542
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2071 times.
2078 if (innodb_optimize_fulltext_only) {
20543
3/6
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
14 if (m_prebuilt->table->fts && m_prebuilt->table->fts->cache &&
20544
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 !dict_table_is_discarded(m_prebuilt->table)) {
20545
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 fts_sync_table(m_prebuilt->table, false, true, false);
20546
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 fts_optimize_table(m_prebuilt->table);
20547 }
20548 7 return (HA_ADMIN_OK);
20549 } else {
20550 2071 return (HA_ADMIN_TRY_ALTER);
20551 }
20552 2078 }
20553
20554 /** Tries to check that an InnoDB table is not corrupted. If corruption is
20555 noticed, prints to stderr information about it. In case of corruption
20556 may also assert a failure and crash the server.
20557 @return HA_ADMIN_CORRUPT or HA_ADMIN_OK */
20558
20559 7593 int ha_innobase::check(THD *thd, /*!< in: user thread handle */
20560 HA_CHECK_OPT *check_opt) /*!< in: check options */
20561 {
20562 dict_index_t *index;
20563 ulint n_rows;
20564 7593 ulint n_rows_in_table = ULINT_UNDEFINED;
20565 7593 ulint n_dups = 0;
20566 7593 bool is_ok = true;
20567 ulint old_isolation_level;
20568 dberr_t ret;
20569
20570
1/2
✓ Branch 0 taken 7593 times.
✗ Branch 1 not taken.
7593 DBUG_TRACE;
20571
2/4
✓ Branch 0 taken 7593 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7593 times.
7593 assert(thd == ha_thd());
20572 #ifdef WITH_WSREP
20573
2/4
✓ Branch 0 taken 7593 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7593 times.
✗ Branch 3 not taken.
7593 DEBUG_SYNC(thd, "ha_innobase_check");
20574 #endif /* WITH_WSREP */
20575
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7593 times.
7593 ut_a(m_prebuilt->trx->magic_n == TRX_MAGIC_N);
20576
2/4
✓ Branch 0 taken 7593 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7593 times.
7593 ut_a(m_prebuilt->trx == thd_to_trx(thd));
20577
20578
1/2
✓ Branch 0 taken 7593 times.
✗ Branch 1 not taken.
7593 TrxInInnoDB trx_in_innodb(m_prebuilt->trx);
20579
20580
2/2
✓ Branch 0 taken 1324 times.
✓ Branch 1 taken 6269 times.
7593 if (m_prebuilt->mysql_template == nullptr) {
20581 /* Build the template; we will use a dummy template
20582 in index scans done in checking */
20583
20584
1/2
✓ Branch 0 taken 1324 times.
✗ Branch 1 not taken.
1324 build_template(true);
20585 }
20586
20587
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 7589 times.
7593 if (dict_table_is_discarded(m_prebuilt->table)) {
20588 4 ib_senderrf(thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_DISCARDED,
20589
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 table->s->table_name.str);
20590
20591 4 return HA_ADMIN_CORRUPT;
20592
20593
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7589 times.
7589 } else if (m_prebuilt->table->ibd_file_missing) {
20594 ib_senderrf(thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_MISSING,
20595 table->s->table_name.str);
20596
20597 return HA_ADMIN_CORRUPT;
20598 }
20599
20600 7589 m_prebuilt->trx->op_info = "checking table";
20601
20602
2/4
✓ Branch 0 taken 7589 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7589 times.
7589 if (m_prebuilt->table->is_corrupted()) {
20603 /* Now that the table is already marked as corrupted,
20604 there is no need to check any index of this table */
20605 m_prebuilt->trx->op_info = "";
20606 if (thd_killed(m_user_thd)) {
20607 thd_set_kill_status(m_user_thd);
20608 }
20609
20610 return HA_ADMIN_CORRUPT;
20611 }
20612
20613 7589 old_isolation_level = m_prebuilt->trx->isolation_level;
20614
20615 /* We must run the index record counts at an isolation level
20616 >= READ COMMITTED, because a dirty read can see a wrong number
20617 of records in some index; to play safe, we use always
20618 REPEATABLE READ here */
20619 7589 m_prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ;
20620
20621
2/4
✓ Branch 0 taken 7589 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7589 times.
7589 ut_ad(!m_prebuilt->table->is_corrupted());
20622
20623
3/4
✓ Branch 0 taken 7589 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11198 times.
✓ Branch 3 taken 7584 times.
18782 for (index = m_prebuilt->table->first_index(); index != nullptr;
20624
1/2
✓ Branch 0 taken 11193 times.
✗ Branch 1 not taken.
11193 index = index->next()) {
20625 /* If this is an index being created or dropped, skip */
20626
3/4
✓ Branch 0 taken 11198 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 11196 times.
11198 if (!index->is_committed()) {
20627 2 continue;
20628 }
20629
20630
6/8
✓ Branch 0 taken 11196 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11196 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11179 times.
✓ Branch 5 taken 17 times.
✓ Branch 6 taken 11179 times.
✓ Branch 7 taken 17 times.
11196 if (!(check_opt->flags & T_QUICK) && !index->is_corrupted()) {
20631 /* Enlarge the fatal lock wait timeout during
20632 CHECK TABLE. */
20633 srv_fatal_semaphore_wait_extend.fetch_add(1);
20634
20635
1/2
✓ Branch 0 taken 11179 times.
✗ Branch 1 not taken.
11179 bool valid = btr_validate_index(index, m_prebuilt->trx, false);
20636
20637 /* Restore the fatal lock wait timeout after
20638 CHECK TABLE. */
20639 srv_fatal_semaphore_wait_extend.fetch_sub(1);
20640
20641
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11179 times.
11179 if (!valid) {
20642 is_ok = false;
20643
20644 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_NOT_KEYFILE,
20645 "InnoDB: The B-tree of"
20646 " index %s is corrupted.",
20647 index->name());
20648 continue;
20649 }
20650 }
20651
20652 /* Instead of invoking change_active_index(), set up
20653 a dummy template for non-locking reads, disabling
20654 access to the clustered index. */
20655 11196 m_prebuilt->index = index;
20656
20657
1/2
✓ Branch 0 taken 11196 times.
✗ Branch 1 not taken.
11196 m_prebuilt->index_usable = m_prebuilt->index->is_usable(m_prebuilt->trx);
20658
20659
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 11179 times.
11196 if (!m_prebuilt->index_usable) {
20660
2/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
17 if (m_prebuilt->index->is_corrupted()) {
20661
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 push_warning_printf(m_user_thd, Sql_condition::SL_WARNING,
20662 HA_ERR_INDEX_CORRUPT,
20663 "InnoDB: Index %s is marked as"
20664 " corrupted",
20665 index->name());
20666 17 is_ok = false;
20667 } else {
20668 push_warning_printf(thd, Sql_condition::SL_WARNING,
20669 HA_ERR_TABLE_DEF_CHANGED,
20670 "InnoDB: Insufficient history for"
20671 " index %s",
20672 index->name());
20673 }
20674 17 continue;
20675 }
20676
20677 11179 m_prebuilt->sql_stat_start = true;
20678 11179 m_prebuilt->template_type = ROW_MYSQL_DUMMY_TEMPLATE;
20679 11179 m_prebuilt->n_template = 0;
20680 11179 m_prebuilt->need_to_access_clustered = false;
20681
20682
1/2
✓ Branch 0 taken 11179 times.
✗ Branch 1 not taken.
11179 m_prebuilt->clear_search_tuples();
20683
20684 11179 m_prebuilt->select_lock_type = LOCK_NONE;
20685
20686
1/2
✓ Branch 0 taken 11179 times.
✗ Branch 1 not taken.
11179 size_t max_threads = thd_parallel_read_threads(m_prebuilt->trx->mysql_thd);
20687
20688 /* Scan this index. */
20689
3/4
✓ Branch 0 taken 11179 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
✓ Branch 3 taken 11110 times.
11179 if (dict_index_is_spatial(index)) {
20690
1/2
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
69 ret = row_count_rtree_recs(m_prebuilt, &n_rows, &n_dups);
20691 } else {
20692
1/2
✓ Branch 0 taken 11109 times.
✗ Branch 1 not taken.
11110 ret = row_scan_index_for_mysql(m_prebuilt, index, max_threads, true,
20693 &n_rows);
20694 }
20695
20696
5/8
✓ Branch 0 taken 11178 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 11176 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
11178 DBUG_EXECUTE_IF(
20697 "dict_set_clust_index_corrupted",
20698 if (index->is_clustered()) { ret = DB_CORRUPTION; });
20699
20700
6/8
✓ Branch 0 taken 11178 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 11161 times.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 11 times.
✓ Branch 7 taken 6 times.
11178 DBUG_EXECUTE_IF(
20701 "dict_set_index_corrupted",
20702 if (!index->is_clustered()) { ret = DB_CORRUPTION; });
20703
20704
6/8
✓ Branch 0 taken 11178 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11178 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 11176 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 11176 times.
11178 if (ret == DB_INTERRUPTED || thd_killed(m_user_thd)) {
20705 /* Do not report error since this could happen
20706 during shutdown */
20707 2 break;
20708 }
20709
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 11163 times.
11176 if (ret != DB_SUCCESS) {
20710 /* Assume some kind of corruption. */
20711
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_NOT_KEYFILE,
20712 "InnoDB: The B-tree of"
20713 " index %s is corrupted.",
20714 index->name());
20715 13 is_ok = false;
20716
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
13 dict_set_corrupted(index);
20717 }
20718
20719
3/4
✓ Branch 0 taken 11174 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7586 times.
✓ Branch 3 taken 3588 times.
11174 if (index == m_prebuilt->table->first_index()) {
20720 7586 n_rows_in_table = n_rows;
20721
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 3501 times.
3542 } else if (!(index->type & DICT_FTS) && (n_rows != n_rows_in_table) &&
20722
5/8
✓ Branch 0 taken 3542 times.
✓ Branch 1 taken 46 times.
✓ Branch 2 taken 41 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 41 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3588 times.
7130 (!index->is_multi_value()) &&
20723 (!dict_index_is_spatial(index) || (n_rows < n_rows_in_table) ||
20724 (n_dups < n_rows - n_rows_in_table))) {
20725 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_NOT_KEYFILE,
20726 "InnoDB: Index '%-.200s' contains %lu"
20727 " entries, should be %lu.",
20728 index->name(), (ulong)n_rows, (ulong)n_rows_in_table);
20729 is_ok = false;
20730 dict_set_corrupted(index);
20731 }
20732 }
20733
20734 /* Restore the original isolation level */
20735 7586 m_prebuilt->trx->isolation_level =
20736 7586 static_cast<trx_t::isolation_level_t>(old_isolation_level);
20737
20738 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
20739 /* We validate the whole adaptive hash index for all tables
20740 at every CHECK TABLE only when QUICK flag is not present. */
20741
20742
4/8
✓ Branch 0 taken 7586 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7586 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 7586 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 7586 times.
7586 if (!(check_opt->flags & T_QUICK) && !btr_search_validate()) {
20743 push_warning(thd, Sql_condition::SL_WARNING, ER_NOT_KEYFILE,
20744 "InnoDB: The adaptive hash index is corrupted.");
20745 is_ok = false;
20746 }
20747 #endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
20748 7586 m_prebuilt->trx->op_info = "";
20749
3/4
✓ Branch 0 taken 7586 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 7584 times.
7586 if (thd_killed(m_user_thd)) {
20750
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 thd_set_kill_status(m_user_thd);
20751 }
20752
20753
5/10
✓ Branch 0 taken 1167 times.
✓ Branch 1 taken 6419 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1167 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7586 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 7586 times.
7586 if (UNIV_UNLIKELY(m_share && m_share->ib_table &&
20754 m_share->ib_table->is_corrupt)) {
20755 return HA_ADMIN_CORRUPT;
20756 }
20757
20758
2/2
✓ Branch 0 taken 7570 times.
✓ Branch 1 taken 16 times.
7586 return is_ok ? HA_ADMIN_OK : HA_ADMIN_CORRUPT;
20759 7590 }
20760
20761 /** Tells something additional to the handler about how to do things.
20762 @return 0 or error number */
20763
20764 945534733 int ha_innobase::extra(enum ha_extra_function operation)
20765 /*!< in: HA_EXTRA_FLUSH or some other flag */
20766 {
20767
1/2
✓ Branch 0 taken 945538185 times.
✗ Branch 1 not taken.
945534733 if (m_prebuilt->table) {
20768 #ifdef UNIV_DEBUG
20769
1/2
✓ Branch 0 taken 945536303 times.
✗ Branch 1 not taken.
945538185 if (m_prebuilt->table->n_ref_count > 0)
20770 #endif /* UNIV_DEBUG */
20771 945536303 update_thd();
20772 }
20773
20774 /* Warning: since it is not sure that MySQL calls external_lock
20775 before calling this function, the trx field in m_prebuilt can be
20776 obsolete! */
20777
20778
13/14
✗ Branch 0 not taken.
✓ Branch 1 taken 101599777 times.
✓ Branch 2 taken 1400803 times.
✓ Branch 3 taken 1431304 times.
✓ Branch 4 taken 198970 times.
✓ Branch 5 taken 74216 times.
✓ Branch 6 taken 107336430 times.
✓ Branch 7 taken 1958984 times.
✓ Branch 8 taken 107336988 times.
✓ Branch 9 taken 2390110 times.
✓ Branch 10 taken 8321 times.
✓ Branch 11 taken 8319 times.
✓ Branch 12 taken 90827755 times.
✓ Branch 13 taken 530963940 times.
945535917 switch (operation) {
20779 case HA_EXTRA_FLUSH:
20780 if (m_prebuilt->blob_heap) {
20781 row_mysql_prebuilt_free_blob_heap(m_prebuilt);
20782 }
20783
20784 if (m_prebuilt->compress_heap) {
20785 row_mysql_prebuilt_free_compress_heap(m_prebuilt);
20786 }
20787
20788 break;
20789 101599777 case HA_EXTRA_RESET_STATE:
20790 101599777 reset_template();
20791 101599771 m_prebuilt->replace = 0;
20792 101599771 m_prebuilt->on_duplicate_key_update = 0;
20793 101599771 break;
20794 1400803 case HA_EXTRA_NO_KEYREAD:
20795 1400803 m_prebuilt->read_just_key = 0;
20796 1400803 break;
20797 1431304 case HA_EXTRA_KEYREAD:
20798 1431304 m_prebuilt->read_just_key = 1;
20799 1431304 break;
20800 198970 case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
20801 198970 m_prebuilt->keep_other_fields_on_keyread = 1;
20802 198970 break;
20803
20804 /* IMPORTANT: m_prebuilt->trx can be obsolete in
20805 this method, because it is not sure that MySQL
20806 calls external_lock before this method with the
20807 parameters below. We must not invoke update_thd()
20808 either, because the calling threads may change.
20809 CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
20810 74216 case HA_EXTRA_INSERT_WITH_UPDATE:
20811 74216 m_prebuilt->on_duplicate_key_update = 1;
20812 74216 break;
20813 107336430 case HA_EXTRA_NO_IGNORE_DUP_KEY:
20814 107336430 m_prebuilt->on_duplicate_key_update = 0;
20815 107336430 break;
20816 1958984 case HA_EXTRA_WRITE_CAN_REPLACE:
20817 1958984 m_prebuilt->replace = 1;
20818 1958984 break;
20819 107336988 case HA_EXTRA_WRITE_CANNOT_REPLACE:
20820 107336988 m_prebuilt->replace = 0;
20821 107336988 break;
20822 2390110 case HA_EXTRA_NO_READ_LOCKING:
20823 2390110 m_prebuilt->no_read_locking = true;
20824 2390110 break;
20825 8321 case HA_EXTRA_BEGIN_ALTER_COPY:
20826 8321 m_prebuilt->table->skip_alter_undo = 1;
20827 8321 break;
20828 8319 case HA_EXTRA_END_ALTER_COPY:
20829 8319 m_prebuilt->table->skip_alter_undo = 0;
20830 8319 break;
20831 90827755 case HA_EXTRA_NO_AUTOINC_LOCKING:
20832 90827755 m_prebuilt->no_autoinc_locking = true;
20833 90827755 break;
20834 945535911 default: /* Do nothing */
20835 ;
20836 }
20837
20838 945535911 return (0);
20839 }
20840
20841 /**
20842 MySQL calls this method at the end of each statement. This method
20843 exists for readability only. ha_innobase::reset() doesn't give any
20844 clue about the method. */
20845
20846 107334995 int ha_innobase::end_stmt() {
20847
2/2
✓ Branch 0 taken 11922294 times.
✓ Branch 1 taken 95412701 times.
107334995 if (m_prebuilt->blob_heap) {
20848 11922294 row_mysql_prebuilt_free_blob_heap(m_prebuilt);
20849 }
20850
20851
2/2
✓ Branch 0 taken 16633 times.
✓ Branch 1 taken 107318521 times.
107335154 if (m_prebuilt->compress_heap) {
20852 16633 row_mysql_prebuilt_free_compress_heap(m_prebuilt);
20853 }
20854
20855 107335154 m_prebuilt->end_stmt();
20856
20857 107335832 reset_template();
20858
20859 107336499 m_ds_mrr.reset();
20860
20861 /* TODO: This should really be reset in reset_template() but for now
20862 it's safer to do it explicitly here. */
20863
20864 /* This is a statement level counter. */
20865 107336725 m_prebuilt->autoinc_last_value = 0;
20866
20867 107336725 m_prebuilt->no_read_locking = false;
20868 107336725 m_prebuilt->no_autoinc_locking = false;
20869
20870 /* This transaction had called ha_innobase::start_stmt() */
20871 107336725 trx_t *trx = m_prebuilt->trx;
20872
20873
4/6
✓ Branch 0 taken 107100456 times.
✓ Branch 1 taken 236372 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 107100688 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 107337060 times.
107336725 if (!m_prebuilt->table->is_temporary() && trx != thd_to_trx(ha_thd())) {
20874 ut_d(ut_error);
20875 ut_o(return (0));
20876 }
20877
20878
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107336902 times.
107337060 ut_ad(!m_prebuilt->replace);
20879
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107336838 times.
107336902 ut_ad(!m_prebuilt->on_duplicate_key_update);
20880
20881
2/2
✓ Branch 0 taken 2044184 times.
✓ Branch 1 taken 105292654 times.
107336838 if (trx->lock.start_stmt) {
20882 2044184 trx->lock.start_stmt = false;
20883 2044184 TrxInInnoDB::end_stmt(trx);
20884 }
20885
20886 107336908 return (0);
20887 }
20888
20889 /**
20890 MySQL calls this method at the end of each statement */
20891
20892 107335049 int ha_innobase::reset() { return (end_stmt()); }
20893
20894 /** MySQL calls this function at the start of each SQL statement inside LOCK
20895 TABLES. Inside LOCK TABLES the "::external_lock" method does not work to mark
20896 SQL statement borders. Note also a special case: if a temporary table is
20897 created inside LOCK TABLES, MySQL has not called external_lock() at all on
20898 that table.
20899 MySQL-5.0 also calls this before each statement in an execution of a stored
20900 procedure. To make the execution more deterministic for binlogging, MySQL-5.0
20901 locks all tables involved in a stored procedure with full explicit table locks
20902 (thd_in_lock_tables(thd) holds in store_lock()) before executing the procedure.
20903 @param[in] thd handle to the user thread
20904 @param[in] lock_type lock type
20905 @return 0 or error code */
20906 2126719 int ha_innobase::start_stmt(THD *thd, thr_lock_type lock_type) {
20907 2126719 trx_t *trx = m_prebuilt->trx;
20908
20909
1/2
✓ Branch 0 taken 2126719 times.
✗ Branch 1 not taken.
2126719 DBUG_TRACE;
20910
20911
1/2
✓ Branch 0 taken 2126719 times.
✗ Branch 1 not taken.
2126719 update_thd(thd);
20912
20913
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2126719 times.
2126719 ut_ad(m_prebuilt->table != nullptr);
20914
20915
1/2
✓ Branch 0 taken 2126719 times.
✗ Branch 1 not taken.
2126719 TrxInInnoDB trx_in_innodb(trx);
20916
20917
2/4
✓ Branch 0 taken 2126719 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2126719 times.
2126719 if (m_prebuilt->table->is_intrinsic()) {
20918 if (thd_sql_command(thd) == SQLCOM_ALTER_TABLE) {
20919 return HA_ERR_WRONG_COMMAND;
20920 }
20921
20922 return 0;
20923 }
20924
20925 2126719 trx = m_prebuilt->trx;
20926
20927
1/2
✓ Branch 0 taken 2126719 times.
✗ Branch 1 not taken.
2126719 innobase_srv_conc_force_exit_innodb(trx);
20928
20929 /* Reset the AUTOINC statement level counter for multi-row INSERTs. */
20930 2126719 trx->n_autoinc_rows = 0;
20931
20932 2126719 m_prebuilt->sql_stat_start = true;
20933 2126719 m_prebuilt->hint_need_to_fetch_extra_cols = 0;
20934
1/2
✓ Branch 0 taken 2126719 times.
✗ Branch 1 not taken.
2126719 reset_template();
20935
20936
7/8
✓ Branch 0 taken 2126719 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23786 times.
✓ Branch 3 taken 2102933 times.
✓ Branch 4 taken 23677 times.
✓ Branch 5 taken 109 times.
✓ Branch 6 taken 27 times.
✓ Branch 7 taken 2126692 times.
2150396 if (m_prebuilt->table->is_temporary() && m_mysql_has_locked &&
20937
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 23650 times.
23677 m_prebuilt->select_lock_type == LOCK_NONE) {
20938 dberr_t error;
20939
20940
3/4
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 25 times.
27 switch (thd_sql_command(thd)) {
20941 2 case SQLCOM_INSERT:
20942 case SQLCOM_UPDATE:
20943 case SQLCOM_DELETE:
20944 case SQLCOM_REPLACE:
20945
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 init_table_handle_for_HANDLER();
20946 2 m_prebuilt->select_lock_type = LOCK_X;
20947 2 m_stored_select_lock_type = LOCK_X;
20948
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 error = row_lock_table(m_prebuilt);
20949
20950
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (error != DB_SUCCESS) {
20951 int st = convert_error_code_to_mysql(error, 0, thd);
20952 return st;
20953 }
20954 2 break;
20955 }
20956 }
20957
20958
2/2
✓ Branch 0 taken 109 times.
✓ Branch 1 taken 2126610 times.
2126719 if (!m_mysql_has_locked) {
20959 /* This handle is for a temporary table created inside
20960 this same LOCK TABLES; since MySQL does NOT call external_lock
20961 in this case, we must use x-row locks inside InnoDB to be
20962 prepared for an update of a row */
20963
20964 109 m_prebuilt->select_lock_type = LOCK_X;
20965
20966
2/2
✓ Branch 0 taken 93349 times.
✓ Branch 1 taken 2033120 times.
2126469 } else if ((trx->isolation_level != TRX_ISO_SERIALIZABLE &&
20967
7/8
✓ Branch 0 taken 2126469 times.
✓ Branch 1 taken 141 times.
✓ Branch 2 taken 93349 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 82789 times.
✓ Branch 5 taken 10560 times.
✓ Branch 6 taken 10607 times.
✓ Branch 7 taken 2116003 times.
4336009 lock_type == TL_READ && thd_sql_command(thd) == SQLCOM_SELECT) ||
20968
5/6
✓ Branch 0 taken 2116050 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 276 times.
✓ Branch 3 taken 2115774 times.
✓ Branch 4 taken 233 times.
✓ Branch 5 taken 43 times.
2116050 (trx->skip_gap_locks() &&
20969
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 196 times.
233 (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT) &&
20970
3/4
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 67 times.
✓ Branch 3 taken 13 times.
80 (thd_sql_command(thd) == SQLCOM_INSERT_SELECT ||
20971
3/4
✓ Branch 0 taken 67 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 63 times.
✓ Branch 3 taken 4 times.
67 thd_sql_command(thd) == SQLCOM_REPLACE_SELECT ||
20972
3/4
✓ Branch 0 taken 63 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 26 times.
63 thd_sql_command(thd) == SQLCOM_UPDATE ||
20973
3/4
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 33 times.
37 thd_sql_command(thd) == SQLCOM_CREATE_TABLE))) {
20974 /* For other than temporary tables, we obtain
20975 no lock for consistent read (plain SELECT).
20976
20977 If this session is using READ COMMITTED or READ
20978 UNCOMMITTED isolation level and MySQL is doing INSERT
20979 INTO... SELECT or REPLACE INTO...SELECT or UPDATE ...
20980 = (SELECT ...) or CREATE ... SELECT... without FOR
20981 UPDATE or IN SHARE MODE in select, then we use
20982 consistent read for select.
20983
20984 See also similar code in ha_innobase::store_lock(). */
20985
20986 10607 m_prebuilt->select_lock_type = LOCK_NONE;
20987 } else {
20988 /* Not a consistent read: restore the
20989 select_lock_type value. The value of
20990 stored_select_lock_type was decided in:
20991 1) ::store_lock(),
20992 2) ::external_lock(),
20993 3) ::init_table_handle_for_HANDLER(). */
20994
20995
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2116003 times.
2116003 ut_a(m_stored_select_lock_type != LOCK_NONE_UNSET);
20996
20997 2116003 m_prebuilt->select_lock_type = m_stored_select_lock_type;
20998 }
20999
21000 2126719 *trx->detailed_error = 0;
21001
21002
1/2
✓ Branch 0 taken 2126719 times.
✗ Branch 1 not taken.
2126719 innobase_register_trx(ht, thd, trx);
21003
21004
3/4
✓ Branch 0 taken 2126719 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 66958 times.
✓ Branch 3 taken 2059761 times.
2126719 if (!trx_is_started(trx)) {
21005 66958 ++trx->will_lock;
21006 }
21007
21008 /* Only do it once per transaction. */
21009
4/4
✓ Branch 0 taken 2044185 times.
✓ Branch 1 taken 82534 times.
✓ Branch 2 taken 2044184 times.
✓ Branch 3 taken 1 times.
2126719 if (!trx->lock.start_stmt && lock_type != TL_UNLOCK) {
21010 2044184 trx->lock.start_stmt = true;
21011
1/2
✓ Branch 0 taken 2044184 times.
✗ Branch 1 not taken.
2044184 TrxInInnoDB::begin_stmt(trx);
21012 }
21013
21014 2126719 return 0;
21015 2126719 }
21016
21017 104455109 trx_t::isolation_level_t innobase_trx_map_isolation_level(
21018 enum_tx_isolation iso) {
21019 trx_t::isolation_level_t trx_isolation_level;
21020
21021
4/5
✓ Branch 0 taken 29533253 times.
✓ Branch 1 taken 62877615 times.
✓ Branch 2 taken 20402 times.
✓ Branch 3 taken 12024165 times.
✗ Branch 4 not taken.
104455109 switch (iso) {
21022 29533253 case ISO_REPEATABLE_READ:
21023 29533253 trx_isolation_level = TRX_ISO_REPEATABLE_READ;
21024 29533253 break;
21025 62877615 case ISO_READ_COMMITTED:
21026 62877615 trx_isolation_level = TRX_ISO_READ_COMMITTED;
21027 62877615 break;
21028 20402 case ISO_SERIALIZABLE:
21029 20402 trx_isolation_level = TRX_ISO_SERIALIZABLE;
21030 20402 break;
21031 12024165 case ISO_READ_UNCOMMITTED:
21032 12024165 trx_isolation_level = TRX_ISO_READ_UNCOMMITTED;
21033 12024165 break;
21034 default:
21035 ut_error;
21036 }
21037
21038 104455435 return trx_isolation_level;
21039 }
21040
21041 /** As MySQL will execute an external lock for every new table it uses when it
21042 starts to process an SQL statement (an exception is when MySQL calls
21043 start_stmt for the handle) we can use this function to store the pointer to
21044 the THD in the handle. We will also use this function to communicate
21045 to InnoDB that a new SQL statement has started and that we must store a
21046 savepoint to our transaction handle, so that we are able to roll back
21047 the SQL statement in case of an error.
21048 @return 0 */
21049
21050 210486321 int ha_innobase::external_lock(THD *thd, /*!< in: handle to the user thread */
21051 int lock_type) /*!< in: lock type */
21052 {
21053
1/2
✓ Branch 0 taken 210489183 times.
✗ Branch 1 not taken.
210486321 DBUG_TRACE;
21054
5/8
✓ Branch 0 taken 210488859 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 210488801 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12628 times.
✓ Branch 5 taken 210476173 times.
✓ Branch 6 taken 12628 times.
✗ Branch 7 not taken.
210489183 DBUG_PRINT("enter", ("lock_type: %d", lock_type));
21055
21056
1/2
✓ Branch 0 taken 210488280 times.
✗ Branch 1 not taken.
210488801 update_thd(thd);
21057
21058 210488280 trx_t *trx = m_prebuilt->trx;
21059
21060
1/2
✓ Branch 0 taken 210489068 times.
✗ Branch 1 not taken.
210488280 enum_sql_command sql_command = (enum_sql_command)thd_sql_command(thd);
21061
21062
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 210488676 times.
210489068 ut_ad(m_prebuilt->table);
21063
21064
2/4
✓ Branch 0 taken 210488240 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 210488240 times.
210488676 if (m_prebuilt->table->is_intrinsic()) {
21065 if (sql_command == SQLCOM_ALTER_TABLE) {
21066 return HA_ERR_WRONG_COMMAND;
21067 }
21068
21069 TrxInInnoDB::begin_stmt(trx);
21070
21071 return 0;
21072 }
21073
21074 /* Statement based binlogging does not work in isolation level
21075 READ UNCOMMITTED and READ COMMITTED since the necessary
21076 locks cannot be taken. In this case, we print an
21077 informative error message and return with an error.
21078 Note: decide_logging_format would give the same error message,
21079 except it cannot give the extra details. */
21080
21081
3/4
✓ Branch 0 taken 26195987 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 571745 times.
✓ Branch 3 taken 25624242 times.
26196058 if (lock_type == F_WRLCK && !(table_flags() & HA_BINLOG_STMT_CAPABLE) &&
21082
3/4
✓ Branch 0 taken 571705 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11264 times.
✓ Branch 3 taken 560441 times.
571745 thd_binlog_format(thd) == BINLOG_FORMAT_STMT &&
21083
10/12
✓ Branch 0 taken 26196058 times.
✓ Branch 1 taken 184292182 times.
✓ Branch 2 taken 11264 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11258 times.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 11258 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 24 times.
✓ Branch 9 taken 11234 times.
✓ Branch 10 taken 24 times.
✓ Branch 11 taken 210488105 times.
236684187 thd_binlog_filter_ok(thd) && thd_sqlcom_can_generate_row_events(thd)) {
21084 24 bool skip = false;
21085
21086 /* used by test case */
21087
2/4
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
24 DBUG_EXECUTE_IF("no_innodb_binlog_errors", skip = true;);
21088
21089
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 if (!skip) {
21090 #ifdef WITH_WSREP
21091 24 bool sql_log_bin_on = thd->variables.option_bits & OPTION_BIN_LOG;
21092
4/4
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 1 times.
47 if (sql_log_bin_on &&
21093
2/8
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 23 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
23 (!wsrep_on(thd) || wsrep_thd_is_local(m_user_thd))) {
21094
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 my_error(ER_BINLOG_STMT_MODE_AND_ROW_ENGINE, MYF(0),
21095 " InnoDB is limited to row-logging when"
21096 " transaction isolation level is"
21097 " READ COMMITTED or READ UNCOMMITTED.");
21098 23 return HA_ERR_LOGGING_IMPOSSIBLE;
21099 }
21100 #else
21101 my_error(ER_BINLOG_STMT_MODE_AND_ROW_ENGINE, MYF(0),
21102 " InnoDB is limited to row-logging when"
21103 " transaction isolation level is"
21104 " READ COMMITTED or READ UNCOMMITTED.");
21105 return HA_ERR_LOGGING_IMPOSSIBLE;
21106 #endif /* WITH_WSREP */
21107 }
21108 }
21109
21110 /* Check for UPDATEs in read-only mode. */
21111
4/4
✓ Branch 0 taken 147307 times.
✓ Branch 1 taken 210340799 times.
✓ Branch 2 taken 146997 times.
✓ Branch 3 taken 310 times.
210488106 if (srv_read_only_mode &&
21112
4/4
✓ Branch 0 taken 146679 times.
✓ Branch 1 taken 318 times.
✓ Branch 2 taken 146678 times.
✓ Branch 3 taken 1 times.
146997 (sql_command == SQLCOM_UPDATE || sql_command == SQLCOM_INSERT ||
21113
2/4
✓ Branch 0 taken 146678 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 146678 times.
✗ Branch 3 not taken.
146678 sql_command == SQLCOM_REPLACE || sql_command == SQLCOM_DROP_TABLE ||
21114
2/4
✓ Branch 0 taken 146678 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 146678 times.
146678 sql_command == SQLCOM_ALTER_TABLE || sql_command == SQLCOM_OPTIMIZE ||
21115
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 146678 times.
✗ Branch 3 not taken.
146678 (sql_command == SQLCOM_CREATE_TABLE && lock_type == F_WRLCK) ||
21116
3/4
✓ Branch 0 taken 146678 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 146375 times.
✓ Branch 3 taken 303 times.
146678 sql_command == SQLCOM_CREATE_INDEX || sql_command == SQLCOM_DROP_INDEX ||
21117
2/2
✓ Branch 0 taken 146372 times.
✓ Branch 1 taken 3 times.
146375 sql_command == SQLCOM_DELETE ||
21118
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 146368 times.
146372 sql_command == SQLCOM_CREATE_COMPRESSION_DICTIONARY ||
21119 sql_command == SQLCOM_DROP_COMPRESSION_DICTIONARY)) {
21120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 939 times.
939 if (sql_command == SQLCOM_CREATE_TABLE) {
21121 ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_INNODB_READ_ONLY);
21122 return HA_ERR_INNODB_READ_ONLY;
21123 } else {
21124
1/2
✓ Branch 0 taken 939 times.
✗ Branch 1 not taken.
939 ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE);
21125 939 return HA_ERR_TABLE_READONLY;
21126 }
21127 }
21128
21129 210487167 m_prebuilt->sql_stat_start = true;
21130 210487167 m_prebuilt->hint_need_to_fetch_extra_cols = 0;
21131
21132
1/2
✓ Branch 0 taken 210486582 times.
✗ Branch 1 not taken.
210487167 reset_template();
21133
21134
4/4
✓ Branch 0 taken 398 times.
✓ Branch 1 taken 409 times.
✓ Branch 2 taken 210485633 times.
✓ Branch 3 taken 142 times.
210486582 switch (m_prebuilt->table->quiesce) {
21135 398 case QUIESCE_START:
21136 /* Check for FLUSH TABLE t WITH READ LOCK; */
21137
4/6
✓ Branch 0 taken 398 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 395 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 395 times.
✗ Branch 5 not taken.
398 if (!srv_read_only_mode && sql_command == SQLCOM_FLUSH &&
21138 lock_type == F_RDLCK) {
21139
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 393 times.
395 if (dict_table_is_discarded(m_prebuilt->table)) {
21140 2 ib_senderrf(trx->mysql_thd, IB_LOG_LEVEL_ERROR,
21141
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 ER_TABLESPACE_DISCARDED, table->s->table_name.str);
21142
21143 2 return HA_ERR_NO_SUCH_TABLE;
21144 }
21145
21146
1/2
✓ Branch 0 taken 393 times.
✗ Branch 1 not taken.
393 row_quiesce_table_start(m_prebuilt->table, trx);
21147
21148 /* Use the transaction instance to track UNLOCK
21149 TABLES. It can be done via START TRANSACTION; too
21150 implicitly. */
21151
21152 393 ++trx->flush_tables;
21153 }
21154 396 break;
21155
21156 409 case QUIESCE_COMPLETE:
21157 /* Check for UNLOCK TABLES; implicit or explicit
21158 or trx interruption. */
21159
6/6
✓ Branch 0 taken 397 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 393 times.
✓ Branch 4 taken 393 times.
✓ Branch 5 taken 16 times.
413 if (trx->flush_tables > 0 &&
21160
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 (lock_type == F_UNLCK || trx_is_interrupted(trx))) {
21161
1/2
✓ Branch 0 taken 393 times.
✗ Branch 1 not taken.
393 row_quiesce_table_complete(m_prebuilt->table, trx);
21162
21163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 393 times.
393 ut_a(trx->flush_tables > 0);
21164 393 --trx->flush_tables;
21165 }
21166
21167 409 break;
21168
21169 210485633 case QUIESCE_NONE:
21170 210485633 break;
21171 }
21172
21173
2/2
✓ Branch 0 taken 26194376 times.
✓ Branch 1 taken 184292204 times.
210486580 if (lock_type == F_WRLCK) {
21174 /* If this is a SELECT, then it is in UPDATE TABLE ...
21175 or SELECT ... FOR UPDATE */
21176 26194376 m_prebuilt->select_lock_type = LOCK_X;
21177 26194376 m_stored_select_lock_type = LOCK_X;
21178 }
21179
21180
4/6
✓ Branch 0 taken 79049881 times.
✓ Branch 1 taken 131436699 times.
✓ Branch 2 taken 79049881 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 210486258 times.
210486580 ut_ad(!(lock_type == F_RDLCK && m_prebuilt->select_lock_type == LOCK_X));
21181
21182
2/2
✓ Branch 0 taken 105244320 times.
✓ Branch 1 taken 105241938 times.
210486258 if (lock_type != F_UNLCK) {
21183 /* MySQL is setting a new table lock */
21184
21185 105244320 *trx->detailed_error = 0;
21186
21187
1/2
✓ Branch 0 taken 105244784 times.
✗ Branch 1 not taken.
105244320 innobase_register_trx(ht, thd, trx);
21188
21189 /*
21190 For reads we will use LOCK_NONE, LOCK_S or LOCK_X according to this chart:
21191 +-----------------------------------------+
21192 | is_dd_table or skip_locking |
21193 +----------------------------------+------+
21194 | false | true |
21195 +----------------------------------| |
21196 | TRANSACTION ISOLATION LEVEL | |
21197 +----------------+-----------------+ |
21198 | < SERIALIZABLE | = SERIALIZABLE | |
21199 +--------------------+----------------+-----------------+------+
21200 | non-locking SELECT | NONE [1] | S [3] | NONE |
21201 | SELECT FOR SHARE | S [2] | S | NONE |
21202 | SELECT FOR UPDATE | X | X | X |
21203 +--------------------+----------------+-----------------+------+
21204 Where LOCK_NONE means a non-locking consistent reads via read-view, and
21205 `no_read_locking` is set to `true` by Server calling
21206 ha_extra().
21207 Notes:
21208 [1,2] The server layer calls external_lock(..,F_RDLCK) which retains the old
21209 value of select_lock_type before the call. In most cases it is the value
21210 set by a previous call to store_lock(..):
21211 [1] For a non-locking SELECT the Server layer calls store_lock(..,TL_READ)
21212 which sets select_lock_type = LOCK_NONE, except for ACL tables which
21213 treat it as in [1].
21214 [2] In case of SELECT FOR SHARE the Server layer calls
21215 store_lock(..,TL_READ_WITH_SHARED_LOCKS) which sets
21216 select_lock_type = LOCK_S
21217 [3] An exception is consistent reads in the AUTOCOMMIT=1 mode:
21218 we know that they are read-only transactions, and they can be serialized
21219 also if performed as consistent reads. Thus we use LOCK_NONE for them.
21220
21221 For non-SELECT commands, there may be still possibility of setting
21222 skip_locking=1. E.g.,
21223 - UPDATE ... WHERE ... (SELECT... acl_table);
21224 - DELETE ... WHERE ... (SELECT... acl_table);
21225 The first entry 'non-locking SELECT' in above table applies in these case.
21226 */
21227
2/2
✓ Branch 0 taken 79049994 times.
✓ Branch 1 taken 26194790 times.
105244784 if (lock_type == F_RDLCK) {
21228 /**
21229 To limit range of circumstances under which transaction's isolation
21230 level can be compromised, we allow disabling readlocks only for DD
21231 and ACL tables.
21232 */
21233
8/10
✓ Branch 0 taken 2331650 times.
✓ Branch 1 taken 76718344 times.
✓ Branch 2 taken 22534 times.
✓ Branch 3 taken 2309116 times.
✓ Branch 4 taken 22534 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 22534 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 126 times.
✓ Branch 9 taken 79049834 times.
79049994 ut_ad(!m_prebuilt->no_read_locking || m_prebuilt->table->is_dd_table ||
21234 is_acl_table(table));
21235
21236
4/4
✓ Branch 0 taken 2491872 times.
✓ Branch 1 taken 76557962 times.
✓ Branch 2 taken 22534 times.
✓ Branch 3 taken 2469338 times.
79049834 if (m_prebuilt->table->is_dd_table || m_prebuilt->no_read_locking) {
21237 76580496 m_prebuilt->select_lock_type = LOCK_NONE;
21238 76580496 m_stored_select_lock_type = LOCK_NONE;
21239 4940093 } else if (trx->isolation_level == TRX_ISO_SERIALIZABLE &&
21240
6/6
✓ Branch 0 taken 1417 times.
✓ Branch 1 taken 2467921 times.
✓ Branch 2 taken 340 times.
✓ Branch 3 taken 1077 times.
✓ Branch 4 taken 33 times.
✓ Branch 5 taken 2469305 times.
2469678 m_prebuilt->select_lock_type == LOCK_NONE &&
21241
3/4
✓ Branch 0 taken 340 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 307 times.
340 thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
21242 33 m_prebuilt->select_lock_type = LOCK_S;
21243 33 m_stored_select_lock_type = LOCK_S;
21244 } else {
21245 // Retain value set earlier for example via store_lock()
21246 // which is LOCK_S or LOCK_NONE
21247
4/6
✓ Branch 0 taken 1383574 times.
✓ Branch 1 taken 1085731 times.
✓ Branch 2 taken 1383574 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2469306 times.
2469305 ut_ad(m_prebuilt->select_lock_type == LOCK_S ||
21248 m_prebuilt->select_lock_type == LOCK_NONE);
21249 }
21250 }
21251
21252 /* Starting from 4.1.9, no InnoDB table lock is taken in LOCK
21253 TABLES if AUTOCOMMIT=1. It does not make much sense to acquire
21254 an InnoDB table lock if it is released immediately at the end
21255 of LOCK TABLES, and InnoDB's table locks in that case cause
21256 VERY easily deadlocks.
21257
21258 We do not set InnoDB table locks if user has not explicitly
21259 requested a table lock. Note that thd_in_lock_tables(thd)
21260 can hold in some cases, e.g., at the start of a stored
21261 procedure call (SQLCOM_CALL). */
21262
21263
2/2
✓ Branch 0 taken 27280468 times.
✓ Branch 1 taken 77964157 times.
105244625 if (m_prebuilt->select_lock_type != LOCK_NONE) {
21264
3/4
✓ Branch 0 taken 3355 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3353 times.
✓ Branch 3 taken 2 times.
3355 if (sql_command == SQLCOM_LOCK_TABLES && THDVAR(thd, table_locks) &&
21265
7/8
✓ Branch 0 taken 3355 times.
✓ Branch 1 taken 27277113 times.
✓ Branch 2 taken 3353 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 154 times.
✓ Branch 5 taken 3199 times.
✓ Branch 6 taken 154 times.
✓ Branch 7 taken 27280314 times.
27283977 thd_test_options(thd, OPTION_NOT_AUTOCOMMIT) &&
21266
2/4
✓ Branch 0 taken 154 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 154 times.
✗ Branch 3 not taken.
154 thd_in_lock_tables(thd)) {
21267
1/2
✓ Branch 0 taken 154 times.
✗ Branch 1 not taken.
154 dberr_t error = row_lock_table(m_prebuilt);
21268
21269
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 154 times.
154 if (error != DB_SUCCESS) {
21270 return convert_error_code_to_mysql(error, 0, thd);
21271 }
21272 }
21273
21274 27280468 trx->mysql_n_tables_locked++;
21275 }
21276
21277 105244625 trx->n_mysql_tables_in_use++;
21278 105244625 m_mysql_has_locked = true;
21279
21280
7/8
✓ Branch 0 taken 105244845 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 87446491 times.
✓ Branch 3 taken 17798354 times.
✓ Branch 4 taken 77631973 times.
✓ Branch 5 taken 9814518 times.
✓ Branch 6 taken 9814868 times.
✓ Branch 7 taken 95429977 times.
182876598 if (!trx_is_started(trx) && (m_prebuilt->select_lock_type != LOCK_NONE ||
21281
2/2
✓ Branch 0 taken 353 times.
✓ Branch 1 taken 77631620 times.
77631973 m_stored_select_lock_type != LOCK_NONE)) {
21282 9814868 ++trx->will_lock;
21283 }
21284
21285
1/2
✓ Branch 0 taken 105245142 times.
✗ Branch 1 not taken.
105244845 TrxInInnoDB::begin_stmt(trx);
21286
21287 #ifdef UNIV_DEBUG
21288
6/8
✓ Branch 0 taken 105245162 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 105245081 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 74323645 times.
✓ Branch 5 taken 30921436 times.
✓ Branch 6 taken 74323645 times.
✓ Branch 7 taken 30921416 times.
105245142 if (thd != nullptr && thd_tx_is_dd_trx(thd)) {
21289 74323645 trx->is_dd_trx = true;
21290 }
21291 #endif /* UNIV_DEBUG */
21292 105245061 return 0;
21293 } else {
21294
1/2
✓ Branch 0 taken 105242234 times.
✗ Branch 1 not taken.
105241938 TrxInInnoDB::end_stmt(trx);
21295
21296
3/4
✓ Branch 0 taken 96504964 times.
✓ Branch 1 taken 8737270 times.
✓ Branch 2 taken 96505667 times.
✗ Branch 3 not taken.
105242234 DEBUG_SYNC_C("ha_innobase_end_statement");
21297 }
21298
21299 /* MySQL is releasing a table lock */
21300
21301 105242937 trx->n_mysql_tables_in_use--;
21302 105242937 m_mysql_has_locked = false;
21303
21304
1/2
✓ Branch 0 taken 105242458 times.
✗ Branch 1 not taken.
105242937 innobase_srv_conc_force_exit_innodb(trx);
21305
21306 /* If the MySQL lock count drops to zero we know that the current SQL
21307 statement has ended */
21308
21309
2/2
✓ Branch 0 taken 31071705 times.
✓ Branch 1 taken 74170753 times.
105242458 if (trx->n_mysql_tables_in_use == 0) {
21310 31071705 trx->mysql_n_tables_locked = 0;
21311 31071705 m_prebuilt->used_in_HANDLER = false;
21312
21313
3/4
✓ Branch 0 taken 31071606 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19492389 times.
✓ Branch 3 taken 11579217 times.
31071705 if (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
21314
3/4
✓ Branch 0 taken 19491557 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 699181 times.
✓ Branch 3 taken 18792376 times.
19492389 if (trx_is_started(trx)) {
21315
1/2
✓ Branch 0 taken 699181 times.
✗ Branch 1 not taken.
699181 innobase_commit(ht, thd, true);
21316 } else {
21317 /* Since the trx state is TRX_NOT_STARTED,
21318 trx_commit() will not be called. Reset
21319 trx->is_dd_trx here */
21320 18792376 ut_d(trx->is_dd_trx = false);
21321 }
21322
21323
4/4
✓ Branch 0 taken 385983 times.
✓ Branch 1 taken 11193234 times.
✓ Branch 2 taken 9828 times.
✓ Branch 3 taken 11569386 times.
11965197 } else if (trx->isolation_level <= TRX_ISO_READ_COMMITTED &&
21324
3/4
✓ Branch 0 taken 385980 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9828 times.
✓ Branch 3 taken 376152 times.
385983 MVCC::is_view_active(trx->read_view)) {
21325
1/2
✓ Branch 0 taken 9828 times.
✗ Branch 1 not taken.
9828 mutex_enter(&trx_sys->mutex);
21326
21327
1/2
✓ Branch 0 taken 9828 times.
✗ Branch 1 not taken.
9828 trx_sys->mvcc->view_close(trx->read_view, true);
21328
21329
1/2
✓ Branch 0 taken 9828 times.
✗ Branch 1 not taken.
9828 mutex_exit(&trx_sys->mutex);
21330 }
21331 }
21332
21333
5/8
✓ Branch 0 taken 105241863 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 79759484 times.
✓ Branch 3 taken 25482379 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 79759484 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 105241863 times.
105241524 if (!trx_is_started(trx) && lock_type != F_UNLCK &&
21334 (m_prebuilt->select_lock_type != LOCK_NONE ||
21335 m_stored_select_lock_type != LOCK_NONE)) {
21336 ++trx->will_lock;
21337 }
21338
21339 105241863 return 0;
21340 210487888 }
21341
21342 /** Here we export InnoDB status variables to MySQL. */
21343 142028 static void innodb_export_status() {
21344
1/2
✓ Branch 0 taken 142028 times.
✗ Branch 1 not taken.
142028 if (innodb_inited) {
21345 142028 srv_export_innodb_status();
21346 }
21347 142027 }
21348
21349 /** Implements the SHOW ENGINE INNODB STATUS command. Sends the output of the
21350 InnoDB Monitor to the client.
21351 @param[in] hton the innodb handlerton
21352 @param[in] thd the MySQL query thread of the caller
21353 @param[in] stat_print print function
21354 @return 0 on success */
21355 279 static int innodb_show_status(handlerton *hton, THD *thd,
21356 stat_print_fn *stat_print) {
21357 static const char truncated_msg[] = "... truncated...\n";
21358 279 const long MAX_STATUS_SIZE = 1048576;
21359 279 ulint trx_list_start = ULINT_UNDEFINED;
21360 279 ulint trx_list_end = ULINT_UNDEFINED;
21361 bool ret_val;
21362
21363
1/2
✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
279 DBUG_TRACE;
21364
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 279 times.
279 assert(hton == innodb_hton_ptr);
21365
21366 /* We don't create the temp files or associated
21367 mutexes in read-only-mode */
21368
21369
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 279 times.
279 if (srv_read_only_mode) {
21370 return 0;
21371 }
21372
21373
1/2
✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
279 trx_t *trx = check_trx_exists(thd);
21374
21375
1/2
✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
279 innobase_srv_conc_force_exit_innodb(trx);
21376
21377
1/2
✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
279 TrxInInnoDB trx_in_innodb(trx);
21378
21379 /* We let the InnoDB Monitor to output at most MAX_STATUS_SIZE
21380 bytes of text. */
21381
21382 char *str;
21383 ssize_t flen;
21384
21385
1/2
✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
279 mutex_enter(&srv_monitor_file_mutex);
21386
1/2
✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
279 rewind(srv_monitor_file);
21387
21388
1/2
✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
279 srv_printf_innodb_monitor(srv_monitor_file, false, &trx_list_start,
21389 &trx_list_end);
21390
21391
1/2
✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
279 os_file_set_eof(srv_monitor_file);
21392
21393
2/4
✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 279 times.
279 if ((flen = ftell(srv_monitor_file)) < 0) {
21394 flen = 0;
21395 }
21396
21397 ssize_t usable_len;
21398
21399
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 279 times.
279 if (flen > MAX_STATUS_SIZE) {
21400 usable_len = MAX_STATUS_SIZE;
21401 srv_truncated_status_writes++;
21402 } else {
21403 279 usable_len = flen;
21404 }
21405
21406 /* allocate buffer for the string, and
21407 read the contents of the temporary file */
21408
21409
1/2
✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
279 str = (char *)my_malloc(PSI_INSTRUMENT_ME, usable_len + 1, MYF(0));
21410
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 279 times.
279 if (!str) {
21411 mutex_exit(&srv_monitor_file_mutex);
21412 return 1;
21413 }
21414
21415
1/2
✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
279 rewind(srv_monitor_file);
21416
21417
1/2
✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
279 if (flen < MAX_STATUS_SIZE) {
21418 /* Display the entire output. */
21419
1/2
✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
279 flen = fread(str, 1, flen, srv_monitor_file);
21420 } else if (trx_list_end < (ulint)flen && trx_list_start < trx_list_end &&
21421 trx_list_start + (flen - trx_list_end) <
21422 MAX_STATUS_SIZE - sizeof truncated_msg - 1) {
21423 /* Omit the beginning of the list of active transactions. */
21424 ssize_t len = fread(str, 1, trx_list_start, srv_monitor_file);
21425
21426 memcpy(str + len, truncated_msg, sizeof truncated_msg - 1);
21427 len += sizeof truncated_msg - 1;
21428 usable_len = (MAX_STATUS_SIZE - 1) - len;
21429 fseek(srv_monitor_file, static_cast<long>(flen - usable_len), SEEK_SET);
21430 len += fread(str + len, 1, usable_len, srv_monitor_file);
21431 flen = len;
21432 } else {
21433 /* Omit the end of the output. */
21434 flen = fread(str, 1, MAX_STATUS_SIZE - 1, srv_monitor_file);
21435 }
21436
21437
1/2
✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
279 mutex_exit(&srv_monitor_file_mutex);
21438
21439
1/2
✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
279 ret_val = stat_print(thd, innobase_hton_name,
21440 static_cast<uint>(strlen(innobase_hton_name)),
21441 STRING_WITH_LEN(""), str, static_cast<uint>(flen));
21442
21443
1/2
✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
279 my_free(str);
21444
21445 279 return ret_val;
21446 279 }
21447
21448 /** Implements Log_resource lock.
21449 @param[in] hton the innodb handlerton
21450 @return false on success */
21451 252 static bool innobase_lock_hton_log(handlerton *hton) {
21452 252 bool ret_val = false;
21453
21454
1/2
✓ Branch 0 taken 252 times.
✗ Branch 1 not taken.
252 DBUG_TRACE;
21455
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 252 times.
252 assert(hton == innodb_hton_ptr);
21456
21457
1/2
✓ Branch 0 taken 252 times.
✗ Branch 1 not taken.
252 log_position_lock(*log_sys);
21458
21459 252 return ret_val;
21460 252 }
21461
21462 /** Implements Log_resource unlock.
21463 @param[in] hton the innodb handlerton
21464 @return false on success */
21465 252 static bool innobase_unlock_hton_log(handlerton *hton) {
21466 252 bool ret_val = false;
21467
21468
1/2
✓ Branch 0 taken 252 times.
✗ Branch 1 not taken.
252 DBUG_TRACE;
21469
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 252 times.
252 assert(hton == innodb_hton_ptr);
21470
21471
1/2
✓ Branch 0 taken 252 times.
✗ Branch 1 not taken.
252 log_position_unlock(*log_sys);
21472
21473 252 return ret_val;
21474 252 }
21475
21476 /** Implements Log_resource collect_info.
21477 @param[in] hton the innodb handlerton
21478 @param[in] json the JSON dom to receive the log info
21479 @return false on success */
21480 251 static bool innobase_collect_hton_log_info(handlerton *hton, Json_dom *json) {
21481 251 bool ret_val = false;
21482 lsn_t lsn;
21483 lsn_t lsn_checkpoint;
21484
21485
1/2
✓ Branch 0 taken 251 times.
✗ Branch 1 not taken.
251 DBUG_TRACE;
21486
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 251 times.
251 assert(hton == innodb_hton_ptr);
21487
21488
1/2
✓ Branch 0 taken 251 times.
✗ Branch 1 not taken.
251 log_position_collect_lsn_info(*log_sys, &lsn, &lsn_checkpoint);
21489
21490 251 Json_object *json_engines = static_cast<Json_object *>(json);
21491
1/2
✓ Branch 0 taken 251 times.
✗ Branch 1 not taken.
251 Json_object json_innodb;
21492 251 Json_int json_lsn(lsn);
21493 251 Json_int json_lsn_checkpoint(lsn_checkpoint);
21494
21495
2/4
✓ Branch 0 taken 251 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 251 times.
✗ Branch 3 not taken.
251 ret_val = json_innodb.add_clone("LSN", &json_lsn);
21496
1/2
✓ Branch 0 taken 251 times.
✗ Branch 1 not taken.
251 if (!ret_val)
21497
2/4
✓ Branch 0 taken 251 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 251 times.
✗ Branch 3 not taken.
251 ret_val = json_innodb.add_clone("LSN_checkpoint", &json_lsn_checkpoint);
21498
3/6
✓ Branch 0 taken 251 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 251 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 251 times.
✗ Branch 5 not taken.
251 if (!ret_val) ret_val = json_engines->add_clone("InnoDB", &json_innodb);
21499
21500 251 return ret_val;
21501 251 }
21502
21503 /** Callback for collecting mutex statistics */
21504 struct ShowStatus {
21505 /** For tracking the mutex metrics */
21506 struct Value {
21507 /** Constructor
21508 @param[in] name Name of the mutex
21509 @param[in] spins Number of spins
21510 @param[in] waits OS waits so far
21511 @param[in] calls Number of calls to enter() */
21512 Value(const char *name, ulint spins, uint64_t waits, uint64_t calls)
21513 : m_name(name), m_spins(spins), m_waits(waits), m_calls(calls) {
21514 /* No op */
21515 }
21516
21517 /** Mutex name */
21518 std::string m_name;
21519
21520 /** Spins so far */
21521 ulint m_spins;
21522
21523 /** Waits so far */
21524 uint64_t m_waits;
21525
21526 /** Number of calls so far */
21527 uint64_t m_calls;
21528 };
21529
21530 /** Order by m_waits, in descending order. */
21531 struct OrderByWaits {
21532 /** @return true if rhs < lhs */
21533 bool operator()(const Value &lhs, const Value &rhs) const UNIV_NOTHROW {
21534 return (rhs.m_waits < lhs.m_waits);
21535 }
21536 };
21537
21538 typedef std::vector<Value, ut::allocator<Value>> Values;
21539
21540 /** Collect the individual latch counts */
21541 struct GetCount {
21542 typedef latch_meta_t::CounterType::Count Count;
21543
21544 /** Constructor
21545 @param[in] name Latch name
21546 @param[in,out] values Put the values here */
21547 363 GetCount(const char *name, Values *values) UNIV_NOTHROW : m_name(name),
21548 363 m_values(values) {
21549 /* No op */
21550 363 }
21551
21552 /** Collect the latch metrics. Ignore entries where the
21553 spins and waits are zero.
21554 @param[in] count The latch metrics */
21555 13657 void operator()(const Count *count) UNIV_NOTHROW {
21556
2/4
✓ Branch 0 taken 13657 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13657 times.
13657 if (count->m_spins > 0 || count->m_waits > 0) {
21557 m_values->push_back(
21558 Value(m_name, count->m_spins, count->m_waits, count->m_calls));
21559 }
21560 13657 }
21561
21562 /** The latch name */
21563 const char *m_name;
21564
21565 /** For collecting the active mutex stats. */
21566 Values *m_values;
21567 };
21568
21569 /** Constructor */
21570 3 ShowStatus() = default;
21571
21572 /** Callback for collecting the stats
21573 @param[in] latch_meta Latch meta data
21574 @return always returns true */
21575 363 bool operator()(latch_meta_t &latch_meta) UNIV_NOTHROW {
21576
1/2
✓ Branch 0 taken 363 times.
✗ Branch 1 not taken.
726 latch_meta.get_counter()->iterate(
21577 363 GetCount{latch_meta.get_name(), &m_values});
21578
21579 363 return (true);
21580 }
21581
21582 /** Implements the SHOW MUTEX STATUS command, for mutexes.
21583 The table structure is like so: Engine | Mutex Name | Status
21584 We store the metrics in the "Status" column as:
21585
21586 spins=N,waits=N,calls=N"
21587
21588 The user has to parse the data unfortunately
21589 @param[in,out] thd the MySQL query thread of the caller
21590 @param[in,out] stat_print function for printing statistics
21591 @return true on success. */
21592 bool to_string(THD *thd, stat_print_fn *stat_print) UNIV_NOTHROW;
21593
21594 /** For collecting the active mutex stats. */
21595 Values m_values;
21596 };
21597
21598 /** Implements the SHOW MUTEX STATUS command, for mutexes.
21599 The table structure is like so: Engine | Mutex Name | Status
21600 We store the metrics in the "Status" column as:
21601
21602 spins=N,waits=N,calls=N"
21603
21604 The user has to parse the data unfortunately
21605 @param[in,out] thd the MySQL query thread of the caller
21606 @param[in,out] stat_print function for printing statistics
21607 @return true on success. */
21608 3 bool ShowStatus::to_string(THD *thd, stat_print_fn *stat_print) UNIV_NOTHROW {
21609 3 uint hton_name_len = (uint)strlen(innobase_hton_name);
21610
21611
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 std::sort(m_values.begin(), m_values.end(), OrderByWaits());
21612
21613 3 Values::iterator end = m_values.end();
21614
21615
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 for (Values::iterator it = m_values.begin(); it != end; ++it) {
21616 int name_len;
21617 char name_buf[IO_SIZE];
21618
21619 name_len = snprintf(name_buf, sizeof(name_buf), "%s", it->m_name.c_str());
21620
21621 int status_len;
21622 char status_buf[IO_SIZE];
21623
21624 status_len = snprintf(status_buf, sizeof(status_buf),
21625 "spins=%lu,waits=%lu,calls=" TRX_ID_FMT,
21626 static_cast<ulong>(it->m_spins),
21627 static_cast<long>(it->m_waits), it->m_calls);
21628
21629 if (stat_print(thd, innobase_hton_name, hton_name_len, name_buf,
21630 static_cast<uint>(name_len), status_buf,
21631 static_cast<uint>(status_len))) {
21632 return (false);
21633 }
21634 }
21635
21636 3 return (true);
21637 }
21638
21639 /** Implements the SHOW MUTEX STATUS command, for mutexes.
21640 @param[in,out] hton the innodb handlerton
21641 @param[in,out] thd the MySQL query thread of the caller
21642 @param[in,out] stat_print function for printing statistics
21643 @return 0 on success. */
21644 3 static int innodb_show_mutex_status(handlerton *hton, THD *thd,
21645 stat_print_fn *stat_print) {
21646
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 DBUG_TRACE;
21647
21648
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 ShowStatus collector;
21649
21650
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 assert(hton == innodb_hton_ptr);
21651
21652
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 mutex_monitor->iterate(collector);
21653
21654
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if (!collector.to_string(thd, stat_print)) {
21655 return 1;
21656 }
21657
21658 3 return 0;
21659 3 }
21660
21661 /** Implements the SHOW MUTEX STATUS command.
21662 @param[in,out] hton the innodb handlerton
21663 @param[in,out] thd the MySQL query thread of the caller
21664 @param[in,out] stat_print function for printing statistics
21665 @return 0 on success. */
21666 3 static int innodb_show_rwlock_status(handlerton *hton, THD *thd,
21667 stat_print_fn *stat_print) {
21668
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 DBUG_TRACE;
21669
21670 3 rw_lock_t *block_rwlock = nullptr;
21671 3 ulint block_rwlock_oswait_count = 0;
21672 3 uint hton_name_len = (uint)strlen(innobase_hton_name);
21673
21674
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 assert(hton == innodb_hton_ptr);
21675
21676
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 mutex_enter(&rw_lock_list_mutex);
21677
21678
6/10
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10236 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 10239 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 10236 times.
✓ Branch 9 taken 3 times.
10239 for (auto rw_lock : rw_lock_list) {
21679
2/2
✓ Branch 0 taken 10073 times.
✓ Branch 1 taken 163 times.
10236 if (rw_lock->count_os_wait == 0) {
21680 10191 continue;
21681 }
21682
21683 int buf1len;
21684 char buf1[IO_SIZE];
21685
21686
2/2
✓ Branch 0 taken 118 times.
✓ Branch 1 taken 45 times.
163 if (rw_lock->is_block_lock) {
21687 118 block_rwlock = rw_lock;
21688 118 block_rwlock_oswait_count += rw_lock->count_os_wait;
21689
21690 118 continue;
21691 }
21692
21693 90 buf1len = snprintf(buf1, sizeof buf1, "rwlock: %s:%lu",
21694 innobase_basename(rw_lock->clocation.filename),
21695
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
45 static_cast<ulong>(rw_lock->clocation.line));
21696
21697 int buf2len;
21698 char buf2[IO_SIZE];
21699
21700 45 buf2len = snprintf(buf2, sizeof buf2, "waits=%lu",
21701 45 static_cast<ulong>(rw_lock->count_os_wait));
21702
21703
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (stat_print(thd, innobase_hton_name, hton_name_len, buf1,
21704 45 static_cast<uint>(buf1len), buf2,
21705
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
45 static_cast<uint>(buf2len))) {
21706 mutex_exit(&rw_lock_list_mutex);
21707
21708 return 1;
21709 }
21710 }
21711
21712
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (block_rwlock != nullptr) {
21713 int buf1len;
21714 char buf1[IO_SIZE];
21715
21716 6 buf1len = snprintf(buf1, sizeof buf1, "sum rwlock: %s:%lu",
21717 innobase_basename(block_rwlock->clocation.filename),
21718
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 static_cast<ulong>(block_rwlock->clocation.line));
21719
21720 int buf2len;
21721 char buf2[IO_SIZE];
21722
21723 3 buf2len = snprintf(buf2, sizeof buf2, "waits=%lu",
21724 static_cast<ulong>(block_rwlock_oswait_count));
21725
21726
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (stat_print(thd, innobase_hton_name, hton_name_len, buf1,
21727 3 static_cast<uint>(buf1len), buf2,
21728
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 static_cast<uint>(buf2len))) {
21729 mutex_exit(&rw_lock_list_mutex);
21730
21731 return 1;
21732 }
21733 }
21734
21735
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 mutex_exit(&rw_lock_list_mutex);
21736
21737 3 return 0;
21738 3 }
21739
21740 /** Implements the SHOW MUTEX STATUS command.
21741 @param[in,out] hton the innodb handlerton
21742 @param[in,out] thd the MySQL query thread of the caller
21743 @param[in,out] stat_print function for printing statistics
21744 @return 0 on success. */
21745 3 static int innodb_show_latch_status(handlerton *hton, THD *thd,
21746 stat_print_fn *stat_print) {
21747 3 int ret = innodb_show_mutex_status(hton, thd, stat_print);
21748
21749
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret != 0) {
21750 return (ret);
21751 }
21752
21753 3 return (innodb_show_rwlock_status(hton, thd, stat_print));
21754 }
21755
21756 /** Return 0 on success and non-zero on failure. Note: the bool return type
21757 seems to be abused here, should be an int.
21758 @param[in] hton the innodb handlerton
21759 @param[in] thd the MySQL query thread of the caller
21760 @param[in] stat_print print function
21761 @param[in] stat_type status to show */
21762 285 static bool innobase_show_status(handlerton *hton, THD *thd,
21763 stat_print_fn *stat_print,
21764 enum ha_stat_type stat_type) {
21765
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 285 times.
285 assert(hton == innodb_hton_ptr);
21766
21767
3/4
✓ Branch 0 taken 279 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
285 switch (stat_type) {
21768 279 case HA_ENGINE_STATUS:
21769 /* Non-zero return value means there was an error. */
21770 279 return (innodb_show_status(hton, thd, stat_print) != 0);
21771
21772 3 case HA_ENGINE_MUTEX:
21773 3 return (innodb_show_latch_status(hton, thd, stat_print) != 0);
21774
21775 3 case HA_ENGINE_LOGS:
21776 /* Not handled */
21777 3 break;
21778 }
21779
21780 /* Success */
21781 3 return (false);
21782 }
21783
21784 /** Handling the shared INNOBASE_SHARE structure that is needed to provide table
21785 locking. Register the table name if it doesn't exist in the hash table. */
21786 4025396 static INNOBASE_SHARE *get_share(const char *table_name) {
21787 INNOBASE_SHARE *share;
21788
21789 4025396 mysql_mutex_lock(&innobase_share_mutex);
21790
21791 4025396 const auto hash_value = ut::hash_string(table_name);
21792
21793
5/6
✗ Branch 0 not taken.
✓ Branch 1 taken 2452267 times.
✓ Branch 2 taken 2181479 times.
✓ Branch 3 taken 270788 times.
✓ Branch 4 taken 2452267 times.
✓ Branch 5 taken 1843917 times.
4296184 HASH_SEARCH(table_name_hash, innobase_open_tables, hash_value,
21794 INNOBASE_SHARE *, share, ut_ad(share->use_count > 0),
21795 !strcmp(share->table_name, table_name));
21796
21797
2/2
✓ Branch 0 taken 1843917 times.
✓ Branch 1 taken 2181479 times.
4025396 if (share == nullptr) {
21798 1843917 uint length = (uint)strlen(table_name);
21799
21800 /* TODO: invoke HASH_MIGRATE if innobase_open_tables
21801 grows too big */
21802
21803 share = reinterpret_cast<INNOBASE_SHARE *>(
21804 1843917 my_malloc(PSI_INSTRUMENT_ME, sizeof(*share) + length + 1,
21805 MYF(MY_FAE | MY_ZEROFILL)));
21806
21807 1843917 share->table_name =
21808 1843917 reinterpret_cast<char *>(memcpy(share + 1, table_name, length + 1));
21809
21810
4/4
✓ Branch 0 taken 1720334 times.
✓ Branch 1 taken 123583 times.
✓ Branch 2 taken 17526 times.
✓ Branch 3 taken 123583 times.
1861443 HASH_INSERT(INNOBASE_SHARE, table_name_hash, innobase_open_tables,
21811 hash_value, share);
21812
21813 /* Index translation table initialization */
21814 1843917 share->idx_trans_tbl.index_mapping = nullptr;
21815 1843917 share->idx_trans_tbl.index_count = 0;
21816 1843917 share->idx_trans_tbl.array_size = 0;
21817 }
21818
21819 4025396 ++share->use_count;
21820
21821 4025396 mysql_mutex_unlock(&innobase_share_mutex);
21822
21823 4025396 return (share);
21824 }
21825
21826 /** Free the shared object that was registered with get_share(). */
21827 3917077 static void free_share(
21828 INNOBASE_SHARE *share) /*!< in/own: table share to free */
21829 {
21830
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3917077 times.
3917077 if (!share) {
21831 return;
21832 }
21833
21834 3917077 mysql_mutex_lock(&innobase_share_mutex);
21835
21836 #ifdef UNIV_DEBUG
21837 INNOBASE_SHARE *share2;
21838 3917082 const auto hash_value = ut::hash_string(share->table_name);
21839
21840
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 4111793 times.
✓ Branch 2 taken 3917082 times.
✓ Branch 3 taken 194711 times.
✓ Branch 4 taken 4111793 times.
✗ Branch 5 not taken.
4111793 HASH_SEARCH(table_name_hash, innobase_open_tables, hash_value,
21841 INNOBASE_SHARE *, share2, ut_ad(share->use_count > 0),
21842 !strcmp(share->table_name, share2->table_name));
21843
21844
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3917082 times.
3917082 ut_a(share2 == share);
21845 #endif /* UNIV_DEBUG */
21846
21847 3917082 --share->use_count;
21848
21849
2/2
✓ Branch 0 taken 1788137 times.
✓ Branch 1 taken 2128945 times.
3917082 if (share->use_count == 0) {
21850 1788137 const auto hash_value = ut::hash_string(share->table_name);
21851
21852
5/6
✓ Branch 0 taken 1709372 times.
✓ Branch 1 taken 78765 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3484 times.
✓ Branch 4 taken 3484 times.
✓ Branch 5 taken 78765 times.
1791621 HASH_DELETE(INNOBASE_SHARE, table_name_hash, innobase_open_tables,
21853 hash_value, share);
21854
21855 /* Free any memory from index translation table */
21856 1788137 ut::free(share->idx_trans_tbl.index_mapping);
21857
21858 1788137 my_free(share);
21859
21860 /* TODO: invoke HASH_MIGRATE if innobase_open_tables
21861 shrinks too much */
21862 }
21863
21864 3917082 mysql_mutex_unlock(&innobase_share_mutex);
21865 }
21866
21867 /** Returns number of THR_LOCK locks used for one instance of InnoDB table.
21868 InnoDB no longer relies on THR_LOCK locks so 0 value is returned.
21869 Instead of THR_LOCK locks InnoDB relies on combination of metadata locks
21870 (e.g. for LOCK TABLES and DDL) and its own locking subsystem.
21871 Note that even though this method returns 0, SQL-layer still calls
21872 "::store_lock()", "::start_stmt()" and "::external_lock()" methods for InnoDB
21873 tables. */
21874
21875 105042241 uint ha_innobase::lock_count(void) const { return 0; }
21876
21877 /** Supposed to convert a MySQL table lock stored in the 'lock' field of the
21878 handle to a proper type before storing pointer to the lock into an array
21879 of pointers.
21880 In practice, since InnoDB no longer relies on THR_LOCK locks and its
21881 lock_count() method returns 0 it just informs storage engine about type
21882 of THR_LOCK which SQL-layer would have acquired for this specific statement
21883 on this specific table.
21884 MySQL also calls this if it wants to reset some table locks to a not-locked
21885 state during the processing of an SQL query. An example is that during a
21886 SELECT the read lock is released early on the 'const' tables where we only
21887 fetch one row. MySQL does not call this when it releases all locks at the
21888 end of an SQL statement.
21889 @return pointer to the current element in the 'to' array. */
21890
21891 105042564 THR_LOCK_DATA **ha_innobase::store_lock(
21892 THD *thd, /*!< in: user thread handle */
21893 THR_LOCK_DATA **to, /*!< in: pointer to the current
21894 element in an array of pointers
21895 to lock structs;
21896 only used as return value */
21897 thr_lock_type lock_type) /*!< in: lock type to store in
21898 'lock'; this may also be
21899 TL_IGNORE */
21900 {
21901 /* Note that trx in this function is NOT necessarily m_prebuilt->trx
21902 because we call update_thd() later, in ::external_lock()! Failure to
21903 understand this caused a serious memory corruption bug in 5.1.11. */
21904
21905
1/2
✓ Branch 0 taken 105043745 times.
✗ Branch 1 not taken.
105042564 trx_t *trx = check_trx_exists(thd);
21906
21907
1/2
✓ Branch 0 taken 105043479 times.
✗ Branch 1 not taken.
105043745 TrxInInnoDB trx_in_innodb(trx);
21908
21909 /* NOTE: MySQL can call this function with lock 'type' TL_IGNORE!
21910 Be careful to ignore TL_IGNORE if we are going to do something with
21911 only 'real' locks! */
21912
21913 /* If no MySQL table is in use, we need to set the isolation level
21914 of the transaction. */
21915
21916
4/4
✓ Branch 0 taken 104933873 times.
✓ Branch 1 taken 109606 times.
✓ Branch 2 taken 104456209 times.
✓ Branch 3 taken 477664 times.
105043479 if (lock_type != TL_IGNORE && trx->n_mysql_tables_in_use == 0) {
21917 104455557 trx->isolation_level =
21918
2/4
✓ Branch 0 taken 104455136 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 104455557 times.
✗ Branch 3 not taken.
104456209 innobase_trx_map_isolation_level(thd_get_trx_isolation(thd));
21919
21920
4/4
✓ Branch 0 taken 74901830 times.
✓ Branch 1 taken 29553727 times.
✓ Branch 2 taken 506 times.
✓ Branch 3 taken 104455001 times.
179357337 if (trx->isolation_level <= TRX_ISO_READ_COMMITTED &&
21921
3/4
✓ Branch 0 taken 74901780 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 506 times.
✓ Branch 3 taken 74901274 times.
74901830 MVCC::is_view_active(trx->read_view)) {
21922 /* At low transaction isolation levels we let
21923 each consistent read set its own snapshot */
21924
21925
1/2
✓ Branch 0 taken 506 times.
✗ Branch 1 not taken.
506 mutex_enter(&trx_sys->mutex);
21926
21927
1/2
✓ Branch 0 taken 506 times.
✗ Branch 1 not taken.
506 trx_sys->mvcc->view_close(trx->read_view, true);
21928
21929
1/2
✓ Branch 0 taken 506 times.
✗ Branch 1 not taken.
506 mutex_exit(&trx_sys->mutex);
21930 }
21931 }
21932
21933
2/4
✓ Branch 0 taken 105043174 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 105043174 times.
105042777 assert(EQ_CURRENT_THD(thd));
21934
1/2
✓ Branch 0 taken 105042766 times.
✗ Branch 1 not taken.
105043174 const bool in_lock_tables = thd_in_lock_tables(thd);
21935
1/2
✓ Branch 0 taken 105043136 times.
✗ Branch 1 not taken.
105042766 const uint sql_command = thd_sql_command(thd);
21936
21937
8/10
✓ Branch 0 taken 74064 times.
✓ Branch 1 taken 104969072 times.
✓ Branch 2 taken 74064 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 74064 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 73754 times.
✓ Branch 7 taken 310 times.
✓ Branch 8 taken 940 times.
✓ Branch 9 taken 105042196 times.
105116890 if (srv_read_only_mode && !m_prebuilt->table->is_intrinsic() &&
21938
4/4
✓ Branch 0 taken 73435 times.
✓ Branch 1 taken 319 times.
✓ Branch 2 taken 73434 times.
✓ Branch 3 taken 1 times.
73754 (sql_command == SQLCOM_UPDATE || sql_command == SQLCOM_INSERT ||
21939
2/4
✓ Branch 0 taken 73434 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 73434 times.
✗ Branch 3 not taken.
73434 sql_command == SQLCOM_REPLACE || sql_command == SQLCOM_DROP_TABLE ||
21940
2/4
✓ Branch 0 taken 73434 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 73434 times.
73434 sql_command == SQLCOM_ALTER_TABLE || sql_command == SQLCOM_OPTIMIZE ||
21941 (sql_command == SQLCOM_CREATE_TABLE &&
21942
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 73434 times.
✗ Branch 3 not taken.
73434 (lock_type >= TL_WRITE_CONCURRENT_INSERT && lock_type <= TL_WRITE)) ||
21943
3/4
✓ Branch 0 taken 73434 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 73131 times.
✓ Branch 3 taken 303 times.
73434 sql_command == SQLCOM_CREATE_INDEX || sql_command == SQLCOM_DROP_INDEX ||
21944
2/2
✓ Branch 0 taken 73128 times.
✓ Branch 1 taken 3 times.
73131 sql_command == SQLCOM_DELETE ||
21945
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 73124 times.
73128 sql_command == SQLCOM_CREATE_COMPRESSION_DICTIONARY ||
21946 sql_command == SQLCOM_DROP_COMPRESSION_DICTIONARY)) {
21947
1/2
✓ Branch 0 taken 940 times.
✗ Branch 1 not taken.
940 ib_senderrf(trx->mysql_thd, IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE);
21948
21949
4/4
✓ Branch 0 taken 91355 times.
✓ Branch 1 taken 104950841 times.
✓ Branch 2 taken 405 times.
✓ Branch 3 taken 90950 times.
105042196 } else if (sql_command == SQLCOM_FLUSH && lock_type == TL_READ_NO_INSERT) {
21950 /* Check for FLUSH TABLES ... WITH READ LOCK */
21951
21952 /* Note: This call can fail, but there is no way to return
21953 the error to the caller. We simply ignore it for now here
21954 and push the error code to the caller where the error is
21955 detected in the function. */
21956
21957
1/2
✓ Branch 0 taken 405 times.
✗ Branch 1 not taken.
405 dberr_t err = row_quiesce_set_state(m_prebuilt->table, QUIESCE_START, trx);
21958
21959
4/6
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 397 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 405 times.
405 ut_a(err == DB_SUCCESS || err == DB_UNSUPPORTED);
21960
21961
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 403 times.
405 if (trx->isolation_level == TRX_ISO_SERIALIZABLE) {
21962 2 m_prebuilt->select_lock_type = LOCK_S;
21963 2 m_stored_select_lock_type = LOCK_S;
21964 } else {
21965 403 m_prebuilt->select_lock_type = LOCK_NONE;
21966 403 m_stored_select_lock_type = LOCK_NONE;
21967 }
21968
21969 /* Check for DROP TABLE */
21970
2/2
✓ Branch 0 taken 105040892 times.
✓ Branch 1 taken 899 times.
105042196 } else if (sql_command == SQLCOM_DROP_TABLE) {
21971 /* MySQL calls this function in DROP TABLE though this table
21972 handle may belong to another thd that is running a query. Let
21973 us in that case skip any changes to the m_prebuilt struct. */
21974
21975 /* Check for LOCK TABLE t1,...,tn WITH SHARED LOCKS */
21976
6/6
✓ Branch 0 taken 78624728 times.
✓ Branch 1 taken 26416164 times.
✓ Branch 2 taken 78622290 times.
✓ Branch 3 taken 2438 times.
✓ Branch 4 taken 20 times.
✓ Branch 5 taken 105038434 times.
105040892 } else if ((lock_type == TL_READ && in_lock_tables) ||
21977
3/4
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 105037908 times.
✓ Branch 3 taken 546 times.
105038454 (lock_type == TL_READ_HIGH_PRIORITY && in_lock_tables) ||
21978
2/2
✓ Branch 0 taken 104916950 times.
✓ Branch 1 taken 120958 times.
105037908 lock_type == TL_READ_WITH_SHARED_LOCKS ||
21979
2/2
✓ Branch 0 taken 104807707 times.
✓ Branch 1 taken 109243 times.
104916950 lock_type == TL_READ_NO_INSERT ||
21980
2/2
✓ Branch 0 taken 28004265 times.
✓ Branch 1 taken 76803442 times.
104807707 (lock_type != TL_IGNORE && sql_command != SQLCOM_SELECT)) {
21981 /* The OR cases above are in this order:
21982 1) MySQL is doing LOCK TABLES ... READ LOCAL, or we
21983 are processing a stored procedure or function, or
21984 2) (we do not know when TL_READ_HIGH_PRIORITY is used), or
21985 3) this is a SELECT ... IN SHARE MODE/FOR SHARE, or
21986 4) we are doing a complex SQL statement like
21987 INSERT INTO ... SELECT ... and the logical logging (MySQL
21988 binlog) requires the use of a locking read, or
21989 MySQL is doing LOCK TABLES ... READ.
21990 5) we let InnoDB do locking reads for all SQL statements that
21991 are not simple SELECTs; note that select_lock_type in this
21992 case may get strengthened in ::external_lock() to LOCK_X.
21993 Note that we MUST use a locking read in all data modifying
21994 SQL statements, because otherwise the execution would not be
21995 serializable, and also the results from the update could be
21996 unexpected if an obsolete consistent read view would be
21997 used. */
21998
21999 /* Use consistent read for checksum table */
22000
22001
4/4
✓ Branch 0 taken 27531373 times.
✓ Branch 1 taken 596834 times.
✓ Branch 2 taken 597074 times.
✓ Branch 3 taken 27531059 times.
55659506 if (sql_command == SQLCOM_CHECKSUM ||
22002
5/6
✓ Branch 0 taken 27531299 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 580037 times.
✓ Branch 3 taken 26951262 times.
✓ Branch 4 taken 572441 times.
✓ Branch 5 taken 7596 times.
27531373 (trx->skip_gap_locks() &&
22003
4/4
✓ Branch 0 taken 1016 times.
✓ Branch 1 taken 571425 times.
✓ Branch 2 taken 8554 times.
✓ Branch 3 taken 58 times.
580037 (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT) &&
22004
2/2
✓ Branch 0 taken 8550 times.
✓ Branch 1 taken 4 times.
8554 (sql_command == SQLCOM_INSERT_SELECT ||
22005
2/2
✓ Branch 0 taken 8489 times.
✓ Branch 1 taken 61 times.
8550 sql_command == SQLCOM_REPLACE_SELECT ||
22006
2/2
✓ Branch 0 taken 117 times.
✓ Branch 1 taken 8372 times.
8489 sql_command == SQLCOM_UPDATE ||
22007 sql_command == SQLCOM_CREATE_TABLE))) {
22008 /* If this session is using READ COMMITTED or READ
22009 UNCOMMITTED isolation level and MySQL is doing INSERT
22010 INTO... SELECT or REPLACE INTO...SELECT or UPDATE ...
22011 = (SELECT ...) or CREATE ... SELECT... without FOR
22012 UPDATE or IN SHARE MODE in select, then we use
22013 consistent read for select.
22014
22015 See also similar code in ha_innobase::start_stmt(). */
22016
22017 597074 m_prebuilt->select_lock_type = LOCK_NONE;
22018 597074 m_stored_select_lock_type = LOCK_NONE;
22019 } else {
22020 27531059 m_prebuilt->select_lock_type = LOCK_S;
22021 27531059 m_stored_select_lock_type = LOCK_S;
22022 }
22023
22024
2/2
✓ Branch 0 taken 76803826 times.
✓ Branch 1 taken 108859 times.
76912685 } else if (lock_type != TL_IGNORE) {
22025 /* We set possible LOCK_X value in external_lock, not yet
22026 here even if this would be SELECT ... FOR UPDATE */
22027
22028 76803826 m_prebuilt->select_lock_type = LOCK_NONE;
22029 76803826 m_stored_select_lock_type = LOCK_NONE;
22030 }
22031
22032 /* Set select mode for SKIP LOCKED / NOWAIT */
22033
2/2
✓ Branch 0 taken 104933123 times.
✓ Branch 1 taken 109939 times.
105043062 if (lock_type != TL_IGNORE) {
22034
3/3
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 96 times.
✓ Branch 2 taken 104933245 times.
104933123 switch (table->pos_in_table_list->lock_descriptor().action) {
22035 100 case THR_SKIP:
22036 100 m_prebuilt->select_mode = SELECT_SKIP_LOCKED;
22037 100 break;
22038 96 case THR_NOWAIT:
22039 96 m_prebuilt->select_mode = SELECT_NOWAIT;
22040 96 break;
22041 104933245 default:
22042 104933245 m_prebuilt->select_mode = SELECT_ORDINARY;
22043 104933245 break;
22044 }
22045 }
22046
22047 /* Ignore SKIP LOCKED / NO_WAIT for high priority transaction */
22048
3/4
✓ Branch 0 taken 105042438 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1231996 times.
✓ Branch 3 taken 103810442 times.
105043380 if (trx_is_high_priority(trx)) {
22049 1231996 m_prebuilt->select_mode = SELECT_ORDINARY;
22050 }
22051
22052
7/8
✓ Branch 0 taken 105042112 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 87455648 times.
✓ Branch 3 taken 17586464 times.
✓ Branch 4 taken 77393847 times.
✓ Branch 5 taken 10061801 times.
✓ Branch 6 taken 10062696 times.
✓ Branch 7 taken 94979416 times.
182436285 if (!trx_is_started(trx) && (m_prebuilt->select_lock_type != LOCK_NONE ||
22053
2/2
✓ Branch 0 taken 848 times.
✓ Branch 1 taken 77392999 times.
77393847 m_stored_select_lock_type != LOCK_NONE)) {
22054 10062696 ++trx->will_lock;
22055 }
22056
22057 #ifdef UNIV_DEBUG
22058
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 105042112 times.
105042112 if (trx->is_dd_trx) {
22059 ut_ad(trx->will_lock == 0 && m_prebuilt->select_lock_type == LOCK_NONE);
22060 }
22061 #endif /* UNIV_DEBUG */
22062
22063 105043596 return (to);
22064 105042112 }
22065
22066 /** Read the next autoinc value. Acquire the relevant locks before reading
22067 the AUTOINC value. If SUCCESS then the table AUTOINC mutex will be locked
22068 on return and all relevant locks acquired.
22069 @return DB_SUCCESS or error code */
22070
22071 7057510 dberr_t ha_innobase::innobase_get_autoinc(
22072 ulonglong *value) /*!< out: autoinc value */
22073 {
22074 7057510 *value = 0;
22075
22076 7057510 m_prebuilt->autoinc_error = innobase_lock_autoinc();
22077
22078
1/2
✓ Branch 0 taken 7057671 times.
✗ Branch 1 not taken.
7057668 if (m_prebuilt->autoinc_error == DB_SUCCESS) {
22079 /* Determine the first value of the interval */
22080 7057671 *value = dict_table_autoinc_read(m_prebuilt->table);
22081
22082 /* It should have been initialized during open. */
22083
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7057632 times.
7057632 if (*value == 0) {
22084 m_prebuilt->autoinc_error = DB_UNSUPPORTED;
22085 dict_table_autoinc_unlock(m_prebuilt->table);
22086 }
22087 }
22088
22089 7057647 return (m_prebuilt->autoinc_error);
22090 }
22091
22092 17644004 void ha_innobase::release_auto_increment() {
22093 17644004 trx_t *trx = m_prebuilt->trx;
22094
1/2
✓ Branch 0 taken 17644036 times.
✗ Branch 1 not taken.
17644004 TrxInInnoDB trx_in_innodb(trx);
22095
22096 /* Clear the trx's autoinc_rows as the operation requiring auto increment
22097 values has been completed.
22098
22099 We usually end up in this scenario when we do not know the correct estimation
22100 of rows in the table in the case of bulk inserts. */
22101
2/2
✓ Branch 0 taken 12521 times.
✓ Branch 1 taken 17631515 times.
17644036 if (trx->n_autoinc_rows > 0) {
22102 12521 trx->n_autoinc_rows = 0;
22103 }
22104 17644036 }
22105
22106 /** Returns the value of the auto-inc counter in *first_value and ~0 on failure.
22107 */
22108
22109 7057386 void ha_innobase::get_auto_increment(
22110 ulonglong offset, /*!< in: table autoinc offset */
22111 ulonglong increment, /*!< in: table autoinc
22112 increment */
22113 ulonglong nb_desired_values, /*!< in: number of values
22114 reqd */
22115 ulonglong *first_value, /*!< out: the autoinc value */
22116 ulonglong *nb_reserved_values) /*!< out: count of reserved
22117 values */
22118 {
22119 trx_t *trx;
22120 dberr_t error;
22121 7057386 ulonglong autoinc = 0;
22122
22123 /* Prepare m_prebuilt->trx in the table handle */
22124
2/4
✓ Branch 0 taken 7057624 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7057675 times.
✗ Branch 3 not taken.
7057386 update_thd(ha_thd());
22125
22126
1/2
✓ Branch 0 taken 7057651 times.
✗ Branch 1 not taken.
7057675 error = innobase_get_autoinc(&autoinc);
22127
22128
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7057650 times.
7057651 if (error != DB_SUCCESS) {
22129 1 *first_value = (~(ulonglong)0);
22130 1 return;
22131 }
22132
22133 /* This is a hack, since nb_desired_values seems to be accurate only
22134 for the first call to get_auto_increment() for multi-row INSERT and
22135 meaningless for other statements e.g, LOAD etc. Subsequent calls to
22136 this method for the same statement results in different values which
22137 don't make sense. Therefore we store the value the first time we are
22138 called and count down from that as rows are written (see write_row()).
22139 */
22140
22141 7057650 trx = m_prebuilt->trx;
22142
22143
1/2
✓ Branch 0 taken 7057660 times.
✗ Branch 1 not taken.
7057650 TrxInInnoDB trx_in_innodb(trx);
22144
22145 /* Note: We can't rely on *first_value since some MySQL engines,
22146 in particular the partition engine, don't initialize it to 0 when
22147 invoking this method. So we are not sure if it's guaranteed to
22148 be 0 or not. */
22149
22150 /* We need the upper limit of the col type to check for
22151 whether we update the table autoinc counter or not. */
22152
1/2
✓ Branch 0 taken 7057672 times.
✗ Branch 1 not taken.
7057660 ulonglong col_max_value = table->next_number_field->get_max_int_value();
22153
22154 /** The following logic is needed to avoid duplicate key error
22155 for autoincrement column.
22156
22157 (1) InnoDB gives the current autoincrement value with respect
22158 to increment and offset value.
22159
22160 (2) Basically it does compute_next_insert_id() logic inside InnoDB
22161 to avoid the current auto increment value changed by handler layer.
22162
22163 (3) It is restricted only for insert operations. */
22164
22165
4/4
✓ Branch 0 taken 15558 times.
✓ Branch 1 taken 7042114 times.
✓ Branch 2 taken 15556 times.
✓ Branch 3 taken 2 times.
7057672 if (increment > 1 && m_prebuilt->table->skip_alter_undo == false &&
22166
2/2
✓ Branch 0 taken 15547 times.
✓ Branch 1 taken 9 times.
15556 autoinc < col_max_value) {
22167 15547 ulonglong diff = ULLONG_MAX - autoinc;
22168 /* Check for overflow */
22169
2/2
✓ Branch 0 taken 15545 times.
✓ Branch 1 taken 2 times.
15547 if (increment <= diff) {
22170 15545 ulonglong prev_auto_inc = autoinc;
22171 15545 autoinc = ((autoinc - 1) + increment - offset) / increment;
22172 15545 autoinc = autoinc * increment + offset;
22173
22174 /* If autoinc exceeds the col_max_value then reset
22175 to old autoinc value. Because in case of non-strict
22176 sql mode, boundary value is not considered as error. */
22177
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 15544 times.
15545 if (autoinc >= col_max_value) {
22178 1 autoinc = prev_auto_inc;
22179 }
22180
22181
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 15482 times.
15545 ut_ad(autoinc > 0);
22182 }
22183 }
22184
22185 /* Called for the first time ? */
22186
2/2
✓ Branch 0 taken 7057534 times.
✓ Branch 1 taken 75 times.
7057609 if (trx->n_autoinc_rows == 0) {
22187 7057534 trx->n_autoinc_rows = (ulint)nb_desired_values;
22188
22189 /* It's possible for nb_desired_values to be 0:
22190 e.g., INSERT INTO T1(C) SELECT C FROM T2; */
22191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7057534 times.
7057534 if (nb_desired_values == 0) {
22192 trx->n_autoinc_rows = 1;
22193 }
22194
22195 7057534 *first_value = std::max(*first_value, autoinc);
22196 /* Not in the middle of a mult-row INSERT. */
22197
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 57 times.
75 } else if (m_prebuilt->autoinc_last_value == 0) {
22198 18 *first_value = std::max(*first_value, autoinc);
22199 /* Check for -ve values. */
22200
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
57 } else if (*first_value > col_max_value && trx->n_autoinc_rows > 0) {
22201 /* Set to next logical value. */
22202 ut_a(autoinc > trx->n_autoinc_rows);
22203 *first_value = (autoinc - trx->n_autoinc_rows) - 1;
22204 }
22205
22206 7057580 *nb_reserved_values = trx->n_autoinc_rows;
22207
22208 /* With old style AUTOINC locking we only update the table's
22209 AUTOINC counter after attempting to insert the row. */
22210
2/2
✓ Branch 0 taken 9500 times.
✓ Branch 1 taken 7048080 times.
7057580 if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING ||
22211
2/2
✓ Branch 0 taken 6567 times.
✓ Branch 1 taken 2933 times.
9500 m_prebuilt->no_autoinc_locking) {
22212 ulonglong current;
22213 ulonglong next_value;
22214
22215
2/2
✓ Branch 0 taken 7054618 times.
✓ Branch 1 taken 29 times.
7054647 current = *first_value > col_max_value ? autoinc : *first_value;
22216
22217 #if 0
22218 /* If the increment step of the auto increment column
22219 decreases then it is not affecting the immediate
22220 next value in the series. */
22221 if (m_prebuilt->autoinc_increment > increment) {
22222 #ifdef WITH_WSREP
22223 WSREP_DEBUG(
22224 "Refresh change in auto-inc configuration"
22225 " from (off: %llu -> %llu)"
22226 " and (inc: %llu -> %llu)."
22227 " Re-align auto increment"
22228 " value for table (%s)"
22229 " THD: %u, current: %llu, autoinc: %llu",
22230 m_prebuilt->autoinc_offset, offset, m_prebuilt->autoinc_increment,
22231 increment, m_prebuilt->table->name.m_name,
22232 wsrep_thd_thread_id(ha_thd()), current, autoinc);
22233 /* MySQL flow will construct last_inserted_id but PXC
22234 can't do so because any values in that range are
22235 potentially unsafe as they were reserved for other node
22236 and if other node has used them it will result in
22237 conflict. So PXC skip this readjustment logic
22238 and re-calibration too as there is no change in
22239 current autoinc value. */
22240 if (!wsrep_on(ha_thd())) {
22241 current = autoinc - m_prebuilt->autoinc_increment;
22242
22243 current =
22244 innobase_next_autoinc(current, 1, increment, 1, col_max_value);
22245 }
22246 #else
22247 current = autoinc - m_prebuilt->autoinc_increment;
22248
22249 current = innobase_next_autoinc(current, 1, increment, 1, col_max_value);
22250 #endif /* WITH_WSREP */
22251
22252 dict_table_autoinc_initialize(m_prebuilt->table, current);
22253
22254 *first_value = current;
22255 }
22256 #endif
22257
22258 /* Compute the last value in the interval */
22259
1/2
✓ Branch 0 taken 7054724 times.
✗ Branch 1 not taken.
7054647 next_value = innobase_next_autoinc(current, *nb_reserved_values, increment,
22260 offset, col_max_value);
22261
22262 7054724 m_prebuilt->autoinc_last_value = next_value;
22263
22264
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7054723 times.
7054724 if (m_prebuilt->autoinc_last_value < *first_value) {
22265 1 *first_value = (~(ulonglong)0);
22266 } else {
22267 /* Update the table autoinc variable */
22268 7054723 dict_table_autoinc_update_if_greater(m_prebuilt->table,
22269
1/2
✓ Branch 0 taken 7054711 times.
✗ Branch 1 not taken.
7054723 m_prebuilt->autoinc_last_value);
22270 }
22271 7054712 } else {
22272 /* This will force write_row() into attempting an update
22273 of the table's AUTOINC counter. */
22274 2933 m_prebuilt->autoinc_last_value = 0;
22275 }
22276
22277 /* The increment to be used to increase the AUTOINC value, we use
22278 this in write_row() and update_row() to increase the autoinc counter
22279 for columns that are filled by the user. We need the offset and
22280 the increment. */
22281 7057645 m_prebuilt->autoinc_offset = offset;
22282 7057645 m_prebuilt->autoinc_increment = increment;
22283
22284
1/2
✓ Branch 0 taken 7057643 times.
✗ Branch 1 not taken.
7057645 dict_table_autoinc_unlock(m_prebuilt->table);
22285 7057643 }
22286
22287 /** See comment in handler.cc */
22288
22289 539 bool ha_innobase::get_error_message(int error, String *buf) {
22290 539 trx_t *trx = check_trx_exists(ha_thd());
22291
22292
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 539 times.
539 if (error == HA_ERR_ENCRYPTION_KEY_MISSING) {
22293 const char *msg =
22294 "Table encrypted but decryption key was not found. "
22295 "Is correct keyring loaded?";
22296 buf->copy(msg, (uint)strlen(msg), system_charset_info);
22297 } else {
22298 539 buf->copy(trx->detailed_error, (uint)strlen(trx->detailed_error),
22299 system_charset_info);
22300 }
22301
22302 539 return false;
22303 }
22304
22305 /** Retrieves the names of the table and the key for which there was a
22306 duplicate entry in the case of HA_ERR_FOREIGN_DUPLICATE_KEY.
22307
22308 If any of the names is not available, then this method will return
22309 false and will not change any of child_table_name or child_key_name.
22310
22311 @param[out] child_table_name Table name
22312 @param[in] child_table_name_len Table name buffer size
22313 @param[out] child_key_name Key name
22314 @param[in] child_key_name_len Key name buffer size
22315
22316 @retval true table and key names were available and were written into the
22317 corresponding out parameters.
22318 @retval false table and key names were not available, the out parameters
22319 were not touched. */
22320 4 bool ha_innobase::get_foreign_dup_key(char *child_table_name,
22321 uint child_table_name_len,
22322 char *child_key_name,
22323 uint child_key_name_len) {
22324 const dict_index_t *err_index;
22325
22326
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 ut_a(m_prebuilt->trx != nullptr);
22327
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 ut_a(m_prebuilt->trx->magic_n == TRX_MAGIC_N);
22328
22329 4 err_index = trx_get_error_index(m_prebuilt->trx);
22330
22331
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err_index == nullptr) {
22332 return (false);
22333 }
22334 /* else */
22335
22336 /* copy table name (and convert from filename-safe encoding to
22337 system_charset_info) */
22338 4 char *p = strchr(err_index->table->name.m_name, '/');
22339
22340 /* strip ".../" prefix if any */
22341
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (p != nullptr) {
22342 4 p++;
22343 } else {
22344 p = err_index->table->name.m_name;
22345 }
22346
22347 size_t len;
22348
22349 4 len = filename_to_tablename(p, child_table_name, child_table_name_len);
22350
22351 4 child_table_name[len] = '\0';
22352
22353 /* copy index name */
22354 4 snprintf(child_key_name, child_key_name_len, "%s", err_index->name());
22355
22356 4 return (true);
22357 }
22358
22359 /** Compares two 'refs'. A 'ref' is the (internal) primary key value of the row.
22360 If there is no explicitly declared non-null unique key or a primary key, then
22361 InnoDB internally uses the row id as the primary key.
22362 @return < 0 if ref1 < ref2, 0 if equal, else > 0 */
22363
22364 5410706 int ha_innobase::cmp_ref(
22365 const uchar *ref1, /*!< in: an (internal) primary key value in the
22366 MySQL key value format */
22367 const uchar *ref2) /*!< in: an (internal) primary key value in the
22368 MySQL key value format */
22369 const {
22370 enum_field_types mysql_type;
22371 Field *field;
22372 KEY_PART_INFO *key_part;
22373 KEY_PART_INFO *key_part_end;
22374 uint len1;
22375 uint len2;
22376 int result;
22377
22378
2/2
✓ Branch 0 taken 4236442 times.
✓ Branch 1 taken 1174264 times.
5410706 if (m_prebuilt->clust_index_was_generated) {
22379 /* The 'ref' is an InnoDB row id */
22380
22381 4236442 return (memcmp(ref1, ref2, DATA_ROW_ID_LEN));
22382 }
22383
22384 /* Do a type-aware comparison of primary key fields. PK fields
22385 are always NOT NULL, so no checks for NULL are performed. */
22386
22387 1174264 key_part = table->key_info[table->s->primary_key].key_part;
22388
22389 1174264 key_part_end =
22390 1174264 key_part + table->key_info[table->s->primary_key].user_defined_key_parts;
22391
22392
2/2
✓ Branch 0 taken 1174885 times.
✓ Branch 1 taken 121867 times.
1296752 for (; key_part != key_part_end; ++key_part) {
22393 1174885 field = key_part->field;
22394 1174885 mysql_type = field->type();
22395
22396
2/4
✓ Branch 0 taken 1174885 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1174885 times.
✗ Branch 3 not taken.
1174885 if (mysql_type == MYSQL_TYPE_TINY_BLOB ||
22397
3/4
✓ Branch 0 taken 1174842 times.
✓ Branch 1 taken 43 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1174842 times.
1174885 mysql_type == MYSQL_TYPE_MEDIUM_BLOB || mysql_type == MYSQL_TYPE_BLOB ||
22398 mysql_type == MYSQL_TYPE_LONG_BLOB) {
22399 /* In the MySQL key value format, a column prefix of
22400 a BLOB is preceded by a 2-byte length field */
22401
22402 43 len1 = innobase_read_from_2_little_endian(ref1);
22403 43 len2 = innobase_read_from_2_little_endian(ref2);
22404
22405 43 result =
22406 43 down_cast<Field_blob *>(field)->cmp(ref1 + 2, len1, ref2 + 2, len2);
22407 } else {
22408 1174842 result = field->key_cmp(ref1, ref2);
22409 }
22410
22411
2/2
✓ Branch 0 taken 1052397 times.
✓ Branch 1 taken 122488 times.
1174885 if (result) {
22412 1052397 return (result);
22413 }
22414
22415 122488 ref1 += key_part->store_length;
22416 122488 ref2 += key_part->store_length;
22417 }
22418
22419 121867 return (0);
22420 }
22421
22422 /** This function is used to find the storage length in bytes of the first n
22423 characters for prefix indexes using a multibyte character set. The function
22424 finds charset information and returns length of prefix_len characters in the
22425 index field in bytes.
22426 @return number of bytes occupied by the first n characters */
22427 95081 ulint innobase_get_at_most_n_mbchars(
22428 ulint charset_id, /*!< in: character set id */
22429 ulint prefix_len, /*!< in: prefix length in bytes of the index
22430 (this has to be divided by mbmaxlen to get the
22431 number of CHARACTERS n in the prefix) */
22432 ulint data_len, /*!< in: length of the string in bytes */
22433 const char *str) /*!< in: character string */
22434 {
22435 ulint char_length; /*!< character length in bytes */
22436 ulint n_chars; /*!< number of characters in prefix */
22437 CHARSET_INFO *charset; /*!< charset used in the field */
22438
22439 95081 charset = get_charset((uint)charset_id, MYF(MY_WME));
22440
22441
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 95083 times.
95082 ut_ad(charset);
22442
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 95083 times.
95083 ut_ad(charset->mbmaxlen);
22443
22444 /* Calculate how many characters at most the prefix index contains */
22445
22446 95083 n_chars = prefix_len / charset->mbmaxlen;
22447
22448 /* If the charset is multi-byte, then we must find the length of the
22449 first at most n chars in the string. If the string contains less
22450 characters than n, then we return the length to the end of the last
22451 character. */
22452
22453
1/2
✓ Branch 0 taken 95083 times.
✗ Branch 1 not taken.
95083 if (charset->mbmaxlen > 1) {
22454 /* my_charpos() returns the byte length of the first n_chars
22455 characters, or a value bigger than the length of str, if
22456 there were not enough full characters in str.
22457
22458 Why does the code below work:
22459 Suppose that we are looking for n UTF-8 characters.
22460
22461 1) If the string is long enough, then the prefix contains at
22462 least n complete UTF-8 characters + maybe some extra
22463 characters + an incomplete UTF-8 character. No problem in
22464 this case. The function returns the pointer to the
22465 end of the nth character.
22466
22467 2) If the string is not long enough, then the string contains
22468 the complete value of a column, that is, only complete UTF-8
22469 characters, and we can store in the column prefix index the
22470 whole string. */
22471
22472 95083 char_length = my_charpos(charset, str, str + data_len, (int)n_chars);
22473
2/2
✓ Branch 0 taken 43494 times.
✓ Branch 1 taken 51603 times.
95097 if (char_length > data_len) {
22474 43494 char_length = data_len;
22475 }
22476 } else if (data_len < prefix_len) {
22477 char_length = data_len;
22478
22479 } else {
22480 char_length = prefix_len;
22481 }
22482
22483 95097 return (char_length);
22484 }
22485
22486 /** This function is used to prepare an X/Open XA distributed transaction.
22487 @return 0 or error number */
22488 4973969 static int innobase_xa_prepare(handlerton *hton, /*!< in: InnoDB handlerton */
22489 THD *thd, /*!< in: handle to the MySQL thread of
22490 the user whose XA transaction should
22491 be prepared */
22492 bool prepare_trx) /*!< in: true - prepare
22493 transaction false - the current
22494 SQL statement ended */
22495 {
22496
1/2
✓ Branch 0 taken 4974059 times.
✗ Branch 1 not taken.
4973969 trx_t *trx = check_trx_exists(thd);
22497
22498
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4974059 times.
4974059 assert(hton == innodb_hton_ptr);
22499
22500
1/2
✓ Branch 0 taken 4973998 times.
✗ Branch 1 not taken.
4974059 thd_get_xid(thd, (MYSQL_XID *)trx->xid);
22501
22502
1/2
✓ Branch 0 taken 4974034 times.
✗ Branch 1 not taken.
4973998 innobase_srv_conc_force_exit_innodb(trx);
22503
22504
1/2
✓ Branch 0 taken 4974027 times.
✗ Branch 1 not taken.
4974034 TrxInInnoDB trx_in_innodb(trx);
22505
22506
5/6
✓ Branch 0 taken 4974041 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4973906 times.
✓ Branch 3 taken 135 times.
✓ Branch 4 taken 121 times.
✓ Branch 5 taken 4973928 times.
9947941 if (trx_in_innodb.is_aborted() ||
22507
2/4
✓ Branch 0 taken 4973914 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4973917 times.
4973906 DBUG_EVALUATE_IF("simulate_xa_failure_prepare_in_engine", 1, 0)) {
22508
1/2
✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
121 innobase_rollback(hton, thd, prepare_trx);
22509
22510
1/2
✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
121 return (convert_error_code_to_mysql(DB_FORCED_ABORT, 0, thd));
22511 }
22512
22513
2/8
✗ Branch 0 not taken.
✓ Branch 1 taken 4973855 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 4973855 times.
4973928 if (!trx_is_registered_for_2pc(trx) && trx_is_started(trx)) {
22514 log_errlog(ERROR_LEVEL, ER_INNODB_UNREGISTERED_TRX_ACTIVE);
22515 }
22516
22517
4/4
✓ Branch 0 taken 4437125 times.
✓ Branch 1 taken 536724 times.
✓ Branch 2 taken 2045361 times.
✓ Branch 3 taken 2928542 times.
9411028 if (prepare_trx ||
22518
3/4
✓ Branch 0 taken 4437179 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1508634 times.
✓ Branch 3 taken 2928545 times.
4437125 (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
22519 /* We were instructed to prepare the whole transaction, or
22520 this is an SQL statement end and autocommit is on */
22521
22522
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2045354 times.
2045361 ut_ad(trx_is_registered_for_2pc(trx));
22523
22524
1/2
✓ Branch 0 taken 2045370 times.
✗ Branch 1 not taken.
2045354 dberr_t err = trx_prepare_for_mysql(trx);
22525
22526
5/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2045369 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 2045370 times.
2045370 ut_ad(err == DB_SUCCESS || err == DB_FORCED_ABORT);
22527
22528
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2045369 times.
2045370 if (err == DB_FORCED_ABORT) {
22529
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 innobase_rollback(hton, thd, prepare_trx);
22530
22531
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 return (convert_error_code_to_mysql(DB_FORCED_ABORT, 0, thd));
22532 }
22533
22534
4/6
✓ Branch 0 taken 2045370 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 2045367 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
2045369 DBUG_EXECUTE_IF("crash_innodb_after_prepare", DBUG_SUICIDE(););
22535
22536 } else {
22537 /* We just mark the SQL statement ended and do not do a
22538 transaction prepare */
22539
22540 /* If we had reserved the auto-inc lock for some
22541 table in this SQL statement we release it now */
22542
22543
1/2
✓ Branch 0 taken 2928557 times.
✗ Branch 1 not taken.
2928542 lock_unlock_table_autoinc(trx);
22544
22545 /* Store the current undo_no of the transaction so that we
22546 know where to roll back if we have to roll back the next
22547 SQL statement */
22548
22549
1/2
✓ Branch 0 taken 2928549 times.
✗ Branch 1 not taken.
2928557 trx_mark_sql_stat_end(trx);
22550 }
22551
22552
5/6
✓ Branch 0 taken 4973922 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4973296 times.
✓ Branch 3 taken 626 times.
✓ Branch 4 taken 4437204 times.
✓ Branch 5 taken 536092 times.
9411119 if (thd_sql_command(thd) != SQLCOM_XA_PREPARE &&
22553 4437203 (prepare_trx ||
22554
3/4
✓ Branch 0 taken 4437203 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1508647 times.
✓ Branch 3 taken 2928556 times.
4437204 !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
22555 /* For mysqlbackup to work the order of transactions in binlog
22556 and InnoDB must be the same. Consider the situation
22557
22558 thread1> prepare; write to binlog; ...
22559 <context switch>
22560 thread2> prepare; write to binlog; commit
22561 thread1> ... commit
22562
22563 The server guarantees that writes to the binary log
22564 and commits are in the same order, so we do not have
22565 to handle this case. */
22566 }
22567
22568 4973921 return (0);
22569 4974043 }
22570
22571 /** This function is used to recover X/Open XA distributed transactions.
22572 @return number of prepared transactions stored in xid_list */
22573 9543 static int innobase_xa_recover(
22574 handlerton *hton, /*!< in: InnoDB handlerton */
22575 XA_recover_txn *txn_list, /*!< in/out: prepared transactions */
22576 uint len, /*!< in: number of slots in xid_list */
22577 MEM_ROOT *mem_root) /*!< in: memory for table names */
22578 {
22579
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9543 times.
9543 assert(hton == innodb_hton_ptr);
22580
22581
2/4
✓ Branch 0 taken 9543 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9543 times.
9543 if (len == 0 || txn_list == nullptr) {
22582 return (0);
22583 }
22584
22585 9543 return (trx_recover_for_mysql(txn_list, len, mem_root));
22586 }
22587
22588 9543 static int innobase_xa_recover_prepared_in_tc(handlerton *hton,
22589 Xa_state_list &xa_list) {
22590
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9543 times.
9543 assert(hton == innodb_hton_ptr);
22591
22592 9543 return (trx_recover_tc_for_mysql(xa_list));
22593 }
22594
22595 /** This function is used to commit one X/Open XA distributed transaction
22596 which is in the prepared state
22597 @return 0 or error number */
22598 608 static xa_status_code innobase_commit_by_xid(
22599 handlerton *hton, XID *xid) /*!< in: X/Open XA transaction identification */
22600 {
22601
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 608 times.
608 assert(hton == innodb_hton_ptr);
22602
22603 608 trx_t *trx = trx_get_trx_by_xid(xid);
22604
22605
2/2
✓ Branch 0 taken 592 times.
✓ Branch 1 taken 16 times.
608 if (trx != nullptr) {
22606
1/2
✓ Branch 0 taken 592 times.
✗ Branch 1 not taken.
592 TrxInInnoDB trx_in_innodb(trx);
22607 #ifdef WITH_WSREP
22608 592 trx->wsrep_recover_xid = xid;
22609 #endif /* WITH_WSREP */
22610
22611
1/2
✓ Branch 0 taken 592 times.
✗ Branch 1 not taken.
592 innobase_commit_low(trx);
22612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 592 times.
592 ut_ad(trx->mysql_thd == nullptr);
22613 /* use cases are: disconnected xa, slave xa, recovery */
22614 592 trx_deregister_from_2pc(trx);
22615
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 592 times.
592 ut_ad(!trx->will_lock); /* trx cache requirement */
22616
22617 #ifdef WITH_WSREP
22618 592 trx->wsrep_recover_xid = NULL;
22619 #endif /* WITH_WSREP */
22620
22621
1/2
✓ Branch 0 taken 592 times.
✗ Branch 1 not taken.
592 trx_free_for_background(trx);
22622
22623 592 return (XA_OK);
22624 592 } else {
22625 16 return (XAER_NOTA);
22626 }
22627 }
22628
22629 /** This function is used to rollback one X/Open XA distributed transaction
22630 which is in the prepared state
22631 @return 0 or error number */
22632 324 static xa_status_code innobase_rollback_by_xid(
22633 handlerton *hton, /*!< in: InnoDB handlerton */
22634 XID *xid) /*!< in: X/Open XA transaction
22635 identification */
22636 {
22637
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 324 times.
324 assert(hton == innodb_hton_ptr);
22638
22639 324 trx_t *trx = trx_get_trx_by_xid(xid);
22640
22641
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 15 times.
324 if (trx != nullptr) {
22642
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 TrxInInnoDB trx_in_innodb(trx);
22643
22644
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 int ret = innobase_rollback_trx(trx);
22645
22646 309 trx_deregister_from_2pc(trx);
22647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 309 times.
309 ut_ad(!trx->will_lock);
22648
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
309 trx_free_for_background(trx);
22649
22650
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 309 times.
309 return (ret != 0 ? XAER_RMERR : XA_OK);
22651 309 } else {
22652 15 return (XAER_NOTA);
22653 }
22654 }
22655
22656 590 static int innobase_set_prepared_in_tc(handlerton *hton, THD *thd) {
22657
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 590 times.
590 assert(hton == innodb_hton_ptr);
22658
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 590 times.
590 assert(thd != nullptr);
22659
22660 590 trx_t *trx = check_trx_exists(thd);
22661
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 590 times.
590 assert(trx != nullptr);
22662
22663 590 thd_get_xid(thd, (MYSQL_XID *)trx->xid);
22664
22665 590 innobase_srv_conc_force_exit_innodb(trx);
22666
22667
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 590 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 590 times.
590 ut_ad(trx_is_registered_for_2pc(trx) || thd == nullptr);
22668
22669 590 dberr_t err = trx_set_prepared_in_tc_for_mysql(trx);
22670
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 590 times.
590 ut_ad(err != DB_FORCED_ABORT);
22671
22672 590 return convert_error_code_to_mysql(err, 0, thd);
22673 }
22674
22675 62 static xa_status_code innobase_set_prepared_in_tc_by_xid(handlerton *hton,
22676 XID *xid) {
22677
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
62 assert(hton == innodb_hton_ptr);
22678
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
62 assert(xid != nullptr);
22679
22680 62 trx_t *trx = trx_get_trx_by_xid(xid);
22681
22682
1/2
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
62 if (trx != nullptr) {
22683 /* Side effect of retrieving the transaction is XID being set to null */
22684 62 *trx->xid = *xid;
22685
22686
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 6 times.
62 if (trx_is_prepared_in_tc(trx)) {
22687 56 return XA_OK;
22688 }
22689
22690 6 innobase_srv_conc_force_exit_innodb(trx);
22691
22692 6 dberr_t err = trx_set_prepared_in_tc_for_mysql(trx);
22693
22694
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 ut_ad(err != DB_FORCED_ABORT);
22695
22696
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 return (err != DB_SUCCESS ? XAER_RMERR : XA_OK);
22697 } else {
22698 return (XAER_NOTA);
22699 }
22700 }
22701
22702 /** */
22703
22704 260 bool ha_innobase::check_if_incompatible_data(HA_CREATE_INFO *info,
22705 uint table_changes) {
22706 260 innobase_copy_frm_flags_from_create_info(m_prebuilt->table, info);
22707
22708
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 260 times.
260 if (table_changes != IS_EQUAL_YES) {
22709 return (COMPATIBLE_DATA_NO);
22710 }
22711
22712 /* Check that auto_increment value was not changed */
22713
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 260 times.
260 if ((info->used_fields & HA_CREATE_USED_AUTO) &&
22714 info->auto_increment_value != 0) {
22715 return (COMPATIBLE_DATA_NO);
22716 }
22717
22718 /* Check that row format didn't change */
22719
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 260 times.
260 if ((info->used_fields & HA_CREATE_USED_ROW_FORMAT) &&
22720 info->row_type != table->s->real_row_type) {
22721 return (COMPATIBLE_DATA_NO);
22722 }
22723
22724 /* Specifying KEY_BLOCK_SIZE requests a rebuild of the table. */
22725
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 260 times.
260 if (info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE) {
22726 return (COMPATIBLE_DATA_NO);
22727 }
22728
22729 260 return (COMPATIBLE_DATA_YES);
22730 }
22731
22732 /** This function reads zip dict-related info from SYS_ZIP_DICT
22733 and SYS_ZIP_DICT_COLS for all columns marked with
22734 COLUMN_FORMAT_TYPE_COMPRESSED flag and updates
22735 zip_dict_name / zip_dict_data for those which have associated
22736 compression dictionaries.
22737
22738 @param thd Thread handle, used to determine whether it is
22739 necessary to lock dict_sys mutex
22740 @param part_name Full table name (including partition part).
22741 Must be non-NULL only if called from
22742 ha_partition.
22743 */
22744 22 void ha_innobase::upgrade_update_field_with_zip_dict_info(
22745 THD *thd, const char *part_name) {
22746
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 DBUG_ENTER("upgrade_update_field_with_zip_dict_info");
22747
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 ut_ad(srv_is_upgrade_mode);
22748
22749 char norm_name[FN_REFLEN];
22750
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
34 normalize_table_name(
22751 12 norm_name, part_name ? part_name : table_share->normalized_path.str);
22752
22753
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 const innodb_session_t *const innodb_session = thd_to_innodb_session(thd);
22754 22 bool dict_locked = innodb_session->is_dict_mutex_locked();
22755
22756
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 dict_table_t *const ib_table = dict_table_open_on_name(
22757 norm_name, dict_locked, false, DICT_ERR_IGNORE_NONE);
22758
22759 /* if dict_table_open_on_name() returns NULL, then it means that
22760 TABLE_SHARE is populated for a table being created and we can
22761 skip filling zip dict info here */
22762
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
22 if (ib_table == nullptr) DBUG_VOID_RETURN;
22763
22764 22 const table_id_t ib_table_id = ib_table->id - DICT_MAX_DD_TABLES;
22765
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 dict_table_close(ib_table, dict_locked, false);
22766
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 22 times.
68 for (uint i = 0; i < table_share->fields; ++i) {
22767 46 Field *const field = table_share->field[i];
22768
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 20 times.
46 if (field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED) {
22769 26 bool reference_found = false;
22770 26 ulint dict_id = 0;
22771
3/5
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
26 switch (dict_get_dictionary_id_by_key(ib_table_id, i, &dict_id)) {
22772 16 case DB_SUCCESS:
22773 16 reference_found = true;
22774 16 break;
22775 10 case DB_RECORD_NOT_FOUND:
22776 10 reference_found = false;
22777 10 break;
22778 default:
22779 ut_error;
22780 }
22781
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 10 times.
26 if (reference_found) {
22782 16 char *local_name = nullptr;
22783 16 ulint local_name_len = 0;
22784 16 char *local_data = nullptr;
22785 16 ulint local_data_len = 0;
22786
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (dict_get_dictionary_info_by_id(dict_id, &local_name,
22787 &local_name_len, &local_data,
22788
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 &local_data_len) != DB_SUCCESS)
22789 ut_error;
22790 else {
22791 16 field->zip_dict_name.str = local_name;
22792 16 field->zip_dict_name.length = local_name_len;
22793 16 field->zip_dict_data.str = local_data;
22794 16 field->zip_dict_data.length = local_data_len;
22795 }
22796 } else {
22797 10 field->zip_dict_name.str = nullptr;
22798 10 field->zip_dict_name.length = 0;
22799 10 field->zip_dict_data.str = nullptr;
22800 10 field->zip_dict_data.length = 0;
22801 }
22802 }
22803 }
22804
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 DBUG_VOID_RETURN;
22805 }
22806
22807 /** Update the system variable innodb_io_capacity_max using the "saved"
22808 value. This function is registered as a callback with MySQL. */
22809 10 static void innodb_io_capacity_max_update(
22810 THD *thd, /*!< in: thread handle */
22811 SYS_VAR *, /*!< in: pointer to
22812 system variable */
22813 void *, /*!< out: where the
22814 formal string goes */
22815 const void *save) /*!< in: immediate result
22816 from check function */
22817 {
22818 10 ulong in_val = *static_cast<const ulong *>(save);
22819
22820
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if (in_val < srv_io_capacity) {
22821 2 in_val = srv_io_capacity;
22822 2 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
22823 "innodb_io_capacity_max cannot be"
22824 " set lower than innodb_io_capacity.");
22825 2 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
22826 "Setting innodb_io_capacity_max to %lu",
22827 srv_io_capacity);
22828 }
22829
22830 10 srv_max_io_capacity = in_val;
22831 10 }
22832
22833 /** Update the system variable innodb_io_capacity using the "saved"
22834 value. This function is registered as a callback with MySQL. */
22835 18 static void innodb_io_capacity_update(
22836 THD *thd, /*!< in: thread handle */
22837 SYS_VAR *, /*!< in: pointer to system variable */
22838 void *, /*!< out: where the formal string goes */
22839 const void *save) /*!< in: immediate result from check function */
22840 {
22841 18 ulong in_val = *static_cast<const ulong *>(save);
22842
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 17 times.
18 if (in_val > srv_max_io_capacity) {
22843 1 in_val = srv_max_io_capacity;
22844 1 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
22845 "innodb_io_capacity cannot be set"
22846 " higher than innodb_io_capacity_max.");
22847 1 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
22848 "Setting innodb_io_capacity to %lu",
22849 srv_max_io_capacity);
22850 }
22851
22852 18 srv_io_capacity = in_val;
22853 18 }
22854
22855 /** Update the system variable innodb_max_dirty_pages_pct using the "saved"
22856 value. This function is registered as a callback with MySQL. */
22857 36 static void innodb_max_dirty_pages_pct_update(
22858 THD *thd, /*!< in: thread handle */
22859 SYS_VAR *, /*!< in: pointer to
22860 system variable */
22861 void *, /*!< out: where the
22862 formal string goes */
22863 const void *save) /*!< in: immediate result
22864 from check function */
22865 {
22866 36 double in_val = *static_cast<const double *>(save);
22867
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 34 times.
36 if (in_val < srv_max_dirty_pages_pct_lwm) {
22868 2 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
22869 "innodb_max_dirty_pages_pct cannot be"
22870 " set lower than"
22871 " innodb_max_dirty_pages_pct_lwm.");
22872 2 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
22873 "Lowering"
22874 " innodb_max_dirty_page_pct_lwm to %lf",
22875 in_val);
22876
22877 2 srv_max_dirty_pages_pct_lwm = in_val;
22878 }
22879
22880 36 srv_max_buf_pool_modified_pct = in_val;
22881 36 }
22882
22883 /** Update the system variable innodb_max_dirty_pages_pct_lwm using the
22884 "saved" value. This function is registered as a callback with MySQL. */
22885 20 static void innodb_max_dirty_pages_pct_lwm_update(
22886 THD *thd, /*!< in: thread handle */
22887 SYS_VAR *, /*!< in: pointer to
22888 system variable */
22889 void *, /*!< out: where the
22890 formal string goes */
22891 const void *save) /*!< in: immediate result
22892 from check function */
22893 {
22894 20 double in_val = *static_cast<const double *>(save);
22895
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 18 times.
20 if (in_val > srv_max_buf_pool_modified_pct) {
22896 2 in_val = srv_max_buf_pool_modified_pct;
22897 2 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
22898 "innodb_max_dirty_pages_pct_lwm"
22899 " cannot be set higher than"
22900 " innodb_max_dirty_pages_pct.");
22901 2 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
22902 "Setting innodb_max_dirty_page_pct_lwm"
22903 " to %lf",
22904 in_val);
22905 }
22906
22907 20 srv_max_dirty_pages_pct_lwm = in_val;
22908 20 }
22909
22910 39 static int innodb_stopword_table_validate(THD *thd, SYS_VAR *, void *save,
22911 struct st_mysql_value *value) {
22912 const char *stopword_table_name;
22913 char buff[STRING_BUFFER_USUAL_SIZE];
22914 39 int len = sizeof(buff);
22915 39 int ret = 1;
22916
22917
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 ut_a(save != nullptr);
22918
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 ut_a(value != nullptr);
22919
22920
1/2
✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
39 stopword_table_name = value->val_str(value, buff, &len);
22921
22922
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 14 times.
39 if (stopword_table_name != nullptr) {
22923
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 23 times.
25 if (stopword_table_name == buff) {
22924 /* Allocate from thd's memroot */
22925
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 stopword_table_name = thd_strmake(thd, stopword_table_name, len);
22926 }
22927 }
22928
22929 /* Validate the stopword table's (if supplied) existence and
22930 of the right format */
22931
7/8
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20 times.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 34 times.
✓ Branch 7 taken 5 times.
39 if (!stopword_table_name || fts_valid_stopword_table(stopword_table_name)) {
22932 34 *static_cast<const char **>(save) = stopword_table_name;
22933 34 ret = 0;
22934 }
22935
22936 39 return (ret);
22937 }
22938
22939 /**
22940 Utility method that checks if user provided valid value.
22941 If yes, then store that in the save variable.
22942 @return 0 on success, 1 on failure.
22943 */
22944 1100 static int check_func_bool(THD *, SYS_VAR *, void *save,
22945 st_mysql_value *value) {
22946 int result;
22947
2/2
✓ Branch 0 taken 993 times.
✓ Branch 1 taken 107 times.
1100 if (value->value_type(value) == MYSQL_VALUE_TYPE_STRING) {
22948 char buff[STRING_BUFFER_USUAL_SIZE];
22949 993 int length = sizeof(buff);
22950
22951
1/2
✓ Branch 0 taken 993 times.
✗ Branch 1 not taken.
993 const char *str = value->val_str(value, buff, &length);
22952
22953
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 993 times.
997 if (str == nullptr) return 1;
22954
22955
1/2
✓ Branch 0 taken 993 times.
✗ Branch 1 not taken.
993 result = find_type(&bool_typelib, str, length, true) - 1;
22956
22957
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 989 times.
993 if (result < 0) return 1;
22958 } else {
22959 long long tmp;
22960
2/4
✓ Branch 0 taken 107 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 107 times.
115 if (value->val_int(value, &tmp) < 0) return 1;
22961
4/4
✓ Branch 0 taken 103 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 99 times.
107 if (tmp > 1 || tmp < 0) return 1;
22962 99 result = static_cast<int>(tmp);
22963 }
22964 1088 *(bool *)save = result ? true : false;
22965 1088 return 0;
22966 }
22967
22968 /**
22969 Utility method that checks if user has correct session administrative
22970 dynamic privileges.
22971 @return 0 on success, 1 on failure.
22972 */
22973 886 static int check_session_admin(THD *thd) {
22974 886 Security_context *sctx = thd->security_context();
22975 886 if (!sctx->has_global_grant(STRING_WITH_LEN("SESSION_VARIABLES_ADMIN"))
22976
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 883 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 885 times.
889 .first &&
22977 3 !sctx->has_global_grant(STRING_WITH_LEN("SYSTEM_VARIABLES_ADMIN"))
22978
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 .first) {
22979 1 return 1;
22980 }
22981 885 return 0;
22982 }
22983
22984 /**
22985 Check if SESSION_VARIABLES_ADMIN granted. Throw SQL error if not.
22986 We also accept SYSTEM_VARIABLES_ADMIN since it doesn't make a lot of
22987 sense to be allowed to set the global variable and not the session ones.
22988
22989 @param thd the session context
22990 @param var the system variable to set value for
22991 @param save set the updated value
22992 @param value A struct that reads us the values from mysqld
22993
22994 @retval 1 failure
22995 @retval 0 success
22996 */
22997 886 static int innodb_check_session_admin(THD *thd, SYS_VAR *var, void *save,
22998 struct st_mysql_value *value) {
22999
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 885 times.
886 if (check_session_admin(thd)) {
23000 1 my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0),
23001 "SYSTEM_VARIABLES_ADMIN or SESSION_VARIABLES_ADMIN");
23002 1 return 1;
23003 }
23004 885 return check_func_bool(thd, var, save, value);
23005 }
23006
23007 5 static void innodb_srv_buffer_pool_in_core_file_update(THD *, SYS_VAR *, void *,
23008 const void *save) {
23009 5 srv_buffer_pool_in_core_file = *(bool *)save;
23010 5 buf_pool_update_madvise();
23011 5 }
23012
23013 /** Validate the requested buffer pool size. Also, reserve the necessary
23014 memory needed for buffer pool resize.
23015 @param[in] thd thread handle
23016 @param[in] buffer_pool_size buffer pool size value to be validated
23017 @param[out] aligned_buffer_pool_size aligned version of buffer_pool_size
23018 if validation succeeds, else original value passed in
23019 @return true on success, false on failure.
23020 */
23021 30 static bool innodb_buffer_pool_size_validate(THD *thd,
23022 longlong buffer_pool_size,
23023 ulint &aligned_buffer_pool_size) {
23024 30 os_rmb;
23025
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 29 times.
30 if (srv_buf_pool_old_size != srv_buf_pool_size) {
23026 1 push_warning(thd, ER_BUFPOOL_RESIZE_INPROGRESS);
23027 1 return false;
23028 }
23029
23030
4/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
29 if (srv_buf_pool_instances > 1 &&
23031 buffer_pool_size < BUF_POOL_SIZE_THRESHOLD) {
23032 #ifdef UNIV_DEBUG
23033 /* Ignore 1G constraint to enable mulitple instances
23034 for debug and test. */
23035
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (srv_buf_pool_debug) {
23036 2 goto debug_set;
23037 }
23038 #endif /* UNIV_DEBUG */
23039
23040 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
23041 "Cannot update innodb_buffer_pool_size"
23042 " to less than 1GB if"
23043 " innodb_buffer_pool_instances > 1.");
23044 return false;
23045 }
23046
23047 #ifdef UNIV_DEBUG
23048 27 debug_set:
23049 #endif /* UNIV_DEBUG */
23050
23051 if constexpr (sizeof(ulint) == 4) {
23052 if (buffer_pool_size > UINT_MAX32) {
23053 push_warning_printf(
23054 thd, Sql_condition::SL_WARNING, ER_WRONG_VALUE_FOR_VAR,
23055 ER_THD(thd, ER_WRONG_VALUE_FOR_VAR), "innodb_buffer_pool_size",
23056 std::to_string(buffer_pool_size).c_str());
23057 return false;
23058 }
23059 }
23060
23061
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 28 times.
29 if (!innodb_empty_free_list_algorithm_allowed(
23062 static_cast<srv_empty_free_list_t>(srv_empty_free_list_algorithm),
23063 buffer_pool_size)) {
23064 1 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
23065 "Cannot update innodb_buffer_pool_size to less than "
23066 "20MB per instance with "
23067 "innodb_empty_free_list_algorithm = backoff.");
23068 1 return false;
23069 }
23070
23071 28 aligned_buffer_pool_size =
23072 28 buf_pool_size_align(static_cast<ulint>(buffer_pool_size));
23073
23074
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 3 times.
28 if (srv_buf_pool_size == static_cast<ulint>(buffer_pool_size)) {
23075 /* nothing to do */
23076
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 23 times.
25 } else if (srv_buf_pool_size == aligned_buffer_pool_size) {
23077 2 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
23078 "InnoDB: Cannot resize buffer pool to lesser than"
23079 " chunk size of %llu bytes.",
23080 srv_buf_pool_chunk_unit);
23081 } else {
23082 23 srv_buf_pool_size = aligned_buffer_pool_size;
23083 23 os_wmb;
23084
23085
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 16 times.
23 if (buffer_pool_size != static_cast<longlong>(aligned_buffer_pool_size)) {
23086
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
7 push_warning_printf(
23087 thd, Sql_condition::SL_WARNING, ER_TRUNCATED_WRONG_VALUE,
23088 ER_THD(thd, ER_TRUNCATED_WRONG_VALUE), "innodb_buffer_pool_size",
23089 14 std::to_string(buffer_pool_size).c_str());
23090 }
23091 }
23092
23093 28 return true;
23094 }
23095
23096 /** Set the variable tbsp_extend_and_initialize. This function is registered
23097 as a callback to MySQL.
23098 On Linux, the variable tbsp_extend_and_initialize will be set to the value
23099 passed by the user. A warning will be printed that the user is not
23100 allowed to change the value if the server is running on Windows
23101 or other posix implementations.
23102 @param[in] thd thread handle
23103 @param[out] var_ptr value to be set after the validation
23104 @param[in] save value set by the user */
23105 19 static void innodb_extend_and_initialize_update(THD *thd, SYS_VAR *,
23106 void *var_ptr,
23107 const void *save) {
23108 19 bool extend_and_initialize [[maybe_unused]] =
23109 *static_cast<const bool *>(save);
23110 #if !defined(NO_FALLOCATE) && defined(UNIV_LINUX)
23111 19 *static_cast<bool *>(var_ptr) = extend_and_initialize;
23112 #else /* !NO_FALLOCATE && UNIV_LINUX */
23113 push_warning_printf(thd, Sql_condition::SL_WARNING,
23114 ER_WARN_VAR_VALUE_CHANGE_NOT_SUPPORTED,
23115 ER_THD(thd, ER_WARN_VAR_VALUE_CHANGE_NOT_SUPPORTED),
23116 "innodb_extend_and_initialize");
23117 *static_cast<bool *>(var_ptr) = true;
23118 #endif /* !NO_FALLOCATE && UNIV_LINUX */
23119 19 }
23120
23121 /** Update the system variable innodb_buffer_pool_size using the "saved"
23122 value. This function is registered as a callback with MySQL.
23123 @param[in] thd thread handle
23124 @param[out] var_ptr where the formal string goes
23125 @param[in] save immediate result from check function */
23126 30 static void innodb_buffer_pool_size_update(THD *thd, SYS_VAR *, void *var_ptr,
23127 const void *save) {
23128 30 longlong requested_buffer_pool_size = *static_cast<const longlong *>(save);
23129 30 ulint aligned_buffer_pool_size = 0u;
23130
3/4
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 2 times.
30 if (innodb_buffer_pool_size_validate(thd, requested_buffer_pool_size,
23131 aligned_buffer_pool_size)) {
23132 28 snprintf(export_vars.innodb_buffer_pool_resize_status,
23133 sizeof(export_vars.innodb_buffer_pool_resize_status),
23134 "Requested to resize buffer pool.");
23135
23136
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 os_event_set(srv_buf_resize_event);
23137
23138
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
56 ib::info(ER_IB_MSG_573)
23139
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 << export_vars.innodb_buffer_pool_resize_status
23140
3/6
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
28 << " (new size: " << aligned_buffer_pool_size << " bytes)";
23141
23142 28 *static_cast<longlong *>(var_ptr) = aligned_buffer_pool_size;
23143 }
23144 30 }
23145
23146 /** Update the system variable innobase_deadlock_detect using the "saved" value.
23147 Makes sure to "wake up" the dedicated deadlock detector thread if needed.
23148 This function is registered as a callback with MySQL.
23149 @param[in] save immediate result from check function */
23150 14 static void innobase_deadlock_detect_update(THD *, SYS_VAR *, void *,
23151 const void *save) {
23152 14 innobase_deadlock_detect = *(bool *)save;
23153 /* In case deadlock detection was disabled for a long time it could happen
23154 that all clients have deadlocked with each other and thus they stopped
23155 changing the wait-for graph, which in turn causes deadlock detection to not
23156 observe any action and thus it will not search for deadlocks. So if we now
23157 change from OFF to ON we need to "kick-start" the process. It never hurts to
23158 do so, so we do it even if we check from ON to OFF */
23159 14 lock_wait_request_check_for_cycles();
23160 14 }
23161
23162 /** Check whether valid argument given to "innodb_fts_internal_tbl_name"
23163 This function is registered as a callback with MySQL.
23164 @param[in] thd thread handle
23165 @param[out] save immediate result for update function
23166 @param[in] value incoming string
23167 @return 0 for valid stopword table */
23168 32 static int innodb_internal_table_validate(THD *thd, SYS_VAR *, void *save,
23169 struct st_mysql_value *value) {
23170 const char *table_name;
23171 char buff[STRING_BUFFER_USUAL_SIZE];
23172 32 int len = sizeof(buff);
23173 32 int ret = 1;
23174 dict_table_t *user_table;
23175 32 MDL_ticket *mdl = nullptr;
23176
23177
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 ut_a(save != nullptr);
23178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 ut_a(value != nullptr);
23179
23180
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 table_name = value->val_str(value, buff, &len);
23181
23182
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 24 times.
32 if (!table_name) {
23183 8 *static_cast<const char **>(save) = nullptr;
23184 8 return (0);
23185
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
24 } else if (table_name == buff) {
23186 /* Allocate memory from thd's mem_root */
23187
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 table_name = thd_strmake(thd, table_name, len);
23188 }
23189
23190 /* If name is longer than NAME_LEN, no need to try to open it */
23191
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
24 if (len >= NAME_LEN) {
23192 2 return (1);
23193 }
23194
23195 user_table =
23196
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 dd_table_open_on_name(thd, &mdl, table_name, false, DICT_ERR_IGNORE_NONE);
23197
23198
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 1 times.
22 if (user_table) {
23199
3/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 1 times.
21 if (dict_table_has_fts_index(user_table)) {
23200 20 *static_cast<const char **>(save) = table_name;
23201 20 ret = 0;
23202 }
23203
23204
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 dd_table_close(user_table, thd, &mdl, false);
23205
23206
6/10
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
21 DBUG_EXECUTE_IF("innodb_evict_autoinc_table", dict_sys_mutex_enter();
23207 dict_table_remove_from_cache_debug(user_table, true);
23208 dict_sys_mutex_exit(););
23209 }
23210
23211 22 return (ret);
23212 }
23213
23214 /** Update the system variable innodb_adaptive_hash_index using the "saved"
23215 value. This function is registered as a callback with MySQL. */
23216 17 static void innodb_adaptive_hash_index_update(
23217 THD *, /*!< in: thread handle */
23218 SYS_VAR *, /*!< in: pointer to
23219 system variable */
23220 void *, /*!< out: where the
23221 formal string goes */
23222 const void *save) /*!< in: immediate result
23223 from check function */
23224 {
23225
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 6 times.
17 if (*(bool *)save) {
23226 11 btr_search_enable(true);
23227 } else {
23228 6 btr_search_disable(true);
23229 }
23230 17 }
23231
23232 /** Update the system variable innodb_cmp_per_index using the "saved"
23233 value. This function is registered as a callback with MySQL. */
23234 75 static void innodb_cmp_per_index_update(
23235 THD *, /*!< in: thread handle */
23236 SYS_VAR *, /*!< in: pointer to
23237 system variable */
23238 void *, /*!< out: where the
23239 formal string goes */
23240 const void *save) /*!< in: immediate result
23241 from check function */
23242 {
23243 /* Reset the stats whenever we enable the table
23244 INFORMATION_SCHEMA.innodb_cmp_per_index. */
23245
4/4
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 35 times.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 4 times.
75 if (!srv_cmp_per_index_enabled && *(bool *)save) {
23246 36 page_zip_reset_stat_per_index();
23247 }
23248
23249 75 srv_cmp_per_index_enabled = *(bool *)save;
23250 75 }
23251
23252 /** Update the system variable innodb_old_blocks_pct using the "saved"
23253 value. This function is registered as a callback with MySQL. */
23254 11 static void innodb_old_blocks_pct_update(
23255 THD *, /*!< in: thread handle */
23256 SYS_VAR *, /*!< in: pointer to
23257 system variable */
23258 void *, /*!< out: where the
23259 formal string goes */
23260 const void *save) /*!< in: immediate result
23261 from check function */
23262 {
23263 11 innobase_old_blocks_pct = static_cast<uint>(
23264 11 buf_LRU_old_ratio_update(*static_cast<const uint *>(save), true));
23265 11 }
23266
23267 /** Update the system variable innodb_old_blocks_pct using the "saved"
23268 value. This function is registered as a callback with MySQL. */
23269 12 static void innodb_change_buffer_max_size_update(
23270 THD *, /*!< in: thread handle */
23271 SYS_VAR *, /*!< in: pointer to
23272 system variable */
23273 void *, /*!< out: where the
23274 formal string goes */
23275 const void *save) /*!< in: immediate result
23276 from check function */
23277 {
23278 12 srv_change_buffer_max_size = (*static_cast<const uint *>(save));
23279 12 ibuf_max_size_update(srv_change_buffer_max_size);
23280 12 }
23281
23282 #ifdef UNIV_DEBUG
23283 static ulong srv_fil_make_page_dirty_debug = 0;
23284 static ulong srv_saved_page_number_debug = 0;
23285
23286 /** Save an InnoDB page number. */
23287 61 static void innodb_save_page_no(THD *, /*!< in: thread handle */
23288 SYS_VAR *, /*!< in: pointer to
23289 system variable */
23290 void *, /*!< out: where the
23291 formal string goes */
23292 const void *save) /*!< in: immediate result
23293 from check function */
23294 {
23295 61 srv_saved_page_number_debug = *static_cast<const ulong *>(save);
23296
23297
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
122 ib::info(ER_IB_MSG_1257) << "Saving InnoDB page number: "
23298
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 << srv_saved_page_number_debug;
23299 61 }
23300
23301 /** Make the first page of given user tablespace dirty. */
23302 57 static void innodb_make_page_dirty(THD *, /*!< in: thread handle */
23303 SYS_VAR *, /*!< in: pointer to
23304 system variable */
23305 void *, /*!< out: where the
23306 formal string goes */
23307 const void *save) /*!< in: immediate result
23308 from check function */
23309 {
23310
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 mtr_t mtr;
23311 57 ulong space_id = *static_cast<const ulong *>(save);
23312 57 page_no_t page_no = srv_saved_page_number_debug;
23313
23314
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 fil_space_t *space = fil_space_acquire_silent(space_id);
23315
23316
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 52 times.
57 if (space == nullptr) {
23317 5 return;
23318 }
23319
23320
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 50 times.
52 if (page_no > space->size) {
23321
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 fil_space_release(space);
23322 2 return;
23323 }
23324
23325 50 auto page_id = page_id_t{space->id, page_no};
23326
23327
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 mtr.start();
23328
23329
2/4
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
50 buf_block_t *block = buf_page_get(page_id, page_size_t(space->flags),
23330 RW_X_LATCH, UT_LOCATION_HERE, &mtr);
23331
23332
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 if (block != nullptr) {
23333 50 byte *page = block->frame;
23334
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 page_type_t page_type = fil_page_get_type(page);
23335
23336 /* Don't dirty a page that is not yet used. */
23337
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 1 times.
50 if (page_type != FIL_PAGE_TYPE_ALLOCATED) {
23338
1/2
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
49 ib::info(ER_IB_MSG_574)
23339
2/4
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
✗ Branch 3 not taken.
49 << "Dirtying page: " << page_id
23340
2/4
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
✗ Branch 3 not taken.
49 << ", page_type=" << fil_get_page_type_str(page_type);
23341
23342 49 dblwr::Force_crash = page_id;
23343
23344
1/2
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
49 mlog_write_ulint(page + FIL_PAGE_TYPE, page_type, MLOG_2BYTES, &mtr);
23345 }
23346 }
23347
23348
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 mtr.commit();
23349
23350
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 fil_space_release(space);
23351
23352
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 if (block != nullptr) {
23353
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
50 buf_flush_sync_all_buf_pools();
23354 }
23355
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
9 }
23356 #endif // UNIV_DEBUG
23357
23358 /** Update the monitor counter according to the "set_option", turn
23359 on/off or reset specified monitor counter. */
23360 9556 static void innodb_monitor_set_option(
23361 const monitor_info_t *monitor_info, /*!< in: monitor info for the monitor
23362 to set */
23363 mon_option_t set_option) /*!< in: Turn on/off reset the
23364 counter */
23365 {
23366 9556 monitor_id_t monitor_id = monitor_info->monitor_id;
23367
23368 /* If module type is MONITOR_GROUP_MODULE, it cannot be
23369 turned on/off individually. It should never use this
23370 function to set options */
23371
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9556 times.
9556 ut_a(!(monitor_info->monitor_type & MONITOR_GROUP_MODULE));
23372
23373
4/5
✓ Branch 0 taken 5905 times.
✓ Branch 1 taken 3316 times.
✓ Branch 2 taken 41 times.
✓ Branch 3 taken 294 times.
✗ Branch 4 not taken.
9556 switch (set_option) {
23374 5905 case MONITOR_TURN_ON:
23375 5905 MONITOR_ON(monitor_id);
23376
4/6
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 5891 times.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
5905 MONITOR_INIT(monitor_id);
23377 5905 MONITOR_SET_START(monitor_id);
23378
23379 /* If the monitor to be turned on uses
23380 existing monitor counter (status variable),
23381 make special processing to remember existing
23382 counter value. */
23383
2/2
✓ Branch 0 taken 3085 times.
✓ Branch 1 taken 2820 times.
5905 if (monitor_info->monitor_type & MONITOR_EXISTING) {
23384 3085 srv_mon_process_existing_counter(monitor_id, MONITOR_TURN_ON);
23385 }
23386
23387
2/2
✓ Branch 0 taken 189 times.
✓ Branch 1 taken 5716 times.
5905 if (MONITOR_IS_ON(MONITOR_LATCHES)) {
23388 189 mutex_monitor->enable();
23389 }
23390 5905 break;
23391
23392 3316 case MONITOR_TURN_OFF:
23393
2/2
✓ Branch 0 taken 988 times.
✓ Branch 1 taken 2328 times.
3316 if (monitor_info->monitor_type & MONITOR_EXISTING) {
23394 988 srv_mon_process_existing_counter(monitor_id, MONITOR_TURN_OFF);
23395 }
23396
23397 3316 MONITOR_OFF(monitor_id);
23398 3316 MONITOR_SET_OFF(monitor_id);
23399
23400
2/2
✓ Branch 0 taken 401 times.
✓ Branch 1 taken 2915 times.
3316 if (!MONITOR_IS_ON(MONITOR_LATCHES)) {
23401 401 mutex_monitor->disable();
23402 }
23403 3316 break;
23404
23405 41 case MONITOR_RESET_VALUE:
23406 41 srv_mon_reset(monitor_id);
23407
23408
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 39 times.
41 if (monitor_id == (MONITOR_LATCHES)) {
23409 2 mutex_monitor->reset();
23410 }
23411 41 break;
23412
23413 294 case MONITOR_RESET_ALL_VALUE:
23414 294 srv_mon_reset_all(monitor_id);
23415 294 mutex_monitor->reset();
23416 294 break;
23417
23418 default:
23419 ut_error;
23420 }
23421 9556 }
23422
23423 /** Find matching InnoDB monitor counters and update their status
23424 according to the "set_option", turn on/off or reset specified
23425 monitor counter. */
23426 53 static void innodb_monitor_update_wildcard(
23427 const char *name, /*!< in: monitor name to match */
23428 mon_option_t set_option) /*!< in: the set option, whether
23429 to turn on/off or reset the counter */
23430 {
23431
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 ut_a(name);
23432
23433
2/2
✓ Branch 0 taken 18126 times.
✓ Branch 1 taken 53 times.
18179 for (ulint use = 0; use < NUM_MONITOR; use++) {
23434 ulint type;
23435 18126 monitor_id_t monitor_id = static_cast<monitor_id_t>(use);
23436 monitor_info_t *monitor_info;
23437
23438
2/2
✓ Branch 0 taken 8541 times.
✓ Branch 1 taken 9585 times.
18126 if (!innobase_wildcasecmp(srv_mon_get_name(monitor_id), name)) {
23439 8541 monitor_info = srv_mon_get_info(monitor_id);
23440
23441 8541 type = monitor_info->monitor_type;
23442
23443 /* If the monitor counter is of MONITOR_MODULE
23444 type, skip it. Except for those also marked with
23445 MONITOR_GROUP_MODULE flag, which can be turned
23446 on only as a module. */
23447
4/4
✓ Branch 0 taken 8002 times.
✓ Branch 1 taken 539 times.
✓ Branch 2 taken 7151 times.
✓ Branch 3 taken 851 times.
8541 if (!(type & MONITOR_MODULE) && !(type & MONITOR_GROUP_MODULE)) {
23448 7151 innodb_monitor_set_option(monitor_info, set_option);
23449 }
23450
23451 /* Need to special handle counters marked with
23452 MONITOR_GROUP_MODULE, turn on the whole module if
23453 any one of it comes here. Currently, only
23454 "module_buf_page" is marked with MONITOR_GROUP_MODULE */
23455
2/2
✓ Branch 0 taken 874 times.
✓ Branch 1 taken 7667 times.
8541 if (type & MONITOR_GROUP_MODULE) {
23456
1/2
✓ Branch 0 taken 874 times.
✗ Branch 1 not taken.
874 if ((monitor_id >= MONITOR_MODULE_BUF_PAGE) &&
23457
1/2
✓ Branch 0 taken 874 times.
✗ Branch 1 not taken.
874 (monitor_id < MONITOR_MODULE_OS)) {
23458
2/2
✓ Branch 0 taken 418 times.
✓ Branch 1 taken 456 times.
874 if (set_option == MONITOR_TURN_ON &&
23459
2/2
✓ Branch 0 taken 407 times.
✓ Branch 1 taken 11 times.
418 MONITOR_IS_ON(MONITOR_MODULE_BUF_PAGE)) {
23460 407 continue;
23461 }
23462
23463 467 srv_mon_set_module_control(MONITOR_MODULE_BUF_PAGE, set_option);
23464 } else {
23465 /* If new monitor is added with
23466 MONITOR_GROUP_MODULE, it needs
23467 to be added here. */
23468 ut_d(ut_error);
23469 }
23470 }
23471 }
23472 }
23473 53 }
23474
23475 /** Given a configuration variable name, find corresponding monitor counter
23476 and return its monitor ID if found.
23477 @return monitor ID if found, MONITOR_NO_MATCH if there is no match */
23478 5406 static ulint innodb_monitor_id_by_name_get(
23479 const char *name) /*!< in: monitor counter namer */
23480 {
23481
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5406 times.
5406 ut_a(name);
23482
23483 /* Search for wild character '%' in the name, if
23484 found, we treat it as a wildcard match. We do not search for
23485 single character wildcard '_' since our monitor names already contain
23486 such character. To avoid confusion, we request user must include
23487 at least one '%' character to activate the wildcard search. */
23488
2/2
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 5295 times.
5406 if (strchr(name, '%')) {
23489 111 return (MONITOR_WILDCARD_MATCH);
23490 }
23491
23492 /* Not wildcard match, check for an exact match */
23493
2/2
✓ Branch 0 taken 899350 times.
✓ Branch 1 taken 15 times.
899365 for (ulint i = 0; i < NUM_MONITOR; i++) {
23494
2/2
✓ Branch 0 taken 5280 times.
✓ Branch 1 taken 894070 times.
899350 if (!innobase_strcasecmp(name,
23495 srv_mon_get_name(static_cast<monitor_id_t>(i)))) {
23496 5280 return (i);
23497 }
23498 }
23499
23500 15 return (MONITOR_NO_MATCH);
23501 }
23502 /** Validate that the passed in monitor name matches at least one
23503 monitor counter name with wildcard compare.
23504 @return true if at least one monitor name matches */
23505 58 static bool innodb_monitor_validate_wildcard_name(
23506 const char *name) /*!< in: monitor counter namer */
23507 {
23508
2/2
✓ Branch 0 taken 5833 times.
✓ Branch 1 taken 5 times.
5838 for (ulint i = 0; i < NUM_MONITOR; i++) {
23509
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 5780 times.
5833 if (!innobase_wildcasecmp(srv_mon_get_name(static_cast<monitor_id_t>(i)),
23510 name)) {
23511 53 return true;
23512 }
23513 }
23514
23515 5 return false;
23516 }
23517 /** Validate the passed in monitor name, find and save the
23518 corresponding monitor name in the function parameter "save".
23519 @return 0 if monitor name is valid */
23520 2713 static int innodb_monitor_valid_byname(
23521 void *save, /*!< out: immediate result
23522 for update function */
23523 const char *name) /*!< in: incoming monitor name */
23524 {
23525 ulint use;
23526 monitor_info_t *monitor_info;
23527
23528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2713 times.
2713 if (!name) {
23529 return (1);
23530 }
23531
23532 2713 use = innodb_monitor_id_by_name_get(name);
23533
23534 /* No monitor name matches, nor it is wildcard match */
23535
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 2698 times.
2713 if (use == MONITOR_NO_MATCH) {
23536 15 return (1);
23537 }
23538
23539
2/2
✓ Branch 0 taken 2640 times.
✓ Branch 1 taken 58 times.
2698 if (use < NUM_MONITOR) {
23540 2640 monitor_info = srv_mon_get_info((monitor_id_t)use);
23541
23542 /* If the monitor counter is marked with
23543 MONITOR_GROUP_MODULE flag, then this counter
23544 cannot be turned on/off individually, instead
23545 it shall be turned on/off as a group using
23546 its module name */
23547
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2636 times.
2640 if ((monitor_info->monitor_type & MONITOR_GROUP_MODULE) &&
23548
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 (!(monitor_info->monitor_type & MONITOR_MODULE))) {
23549 log_errlog(WARNING_LEVEL, ER_INNODB_USE_MONITOR_GROUP_NAME, name);
23550 return (1);
23551 }
23552
23553 } else {
23554
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 ut_a(use == MONITOR_WILDCARD_MATCH);
23555
23556 /* For wildcard match, if there is not a single monitor
23557 counter name that matches, treat it as an invalid
23558 value for the system configuration variables */
23559
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 53 times.
58 if (!innodb_monitor_validate_wildcard_name(name)) {
23560 5 return (1);
23561 }
23562 }
23563
23564 /* Save the configure name for innodb_monitor_update() */
23565 2693 *static_cast<const char **>(save) = name;
23566
23567 2693 return (0);
23568 }
23569 /** Validate passed-in "value" is a valid monitor counter name.
23570 This function is registered as a callback with MySQL.
23571 @return 0 for valid name */
23572 2719 static int innodb_monitor_validate(
23573 THD *, /*!< in: thread handle */
23574 SYS_VAR *, /*!< in: pointer to system
23575 variable */
23576 void *save, /*!< out: immediate result
23577 for update function */
23578 struct st_mysql_value *value) /*!< in: incoming string */
23579 {
23580 const char *name;
23581 char *monitor_name;
23582 char buff[STRING_BUFFER_USUAL_SIZE];
23583 2719 int len = sizeof(buff);
23584 int ret;
23585
23586
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2719 times.
2719 ut_a(save != nullptr);
23587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2719 times.
2719 ut_a(value != nullptr);
23588
23589
1/2
✓ Branch 0 taken 2719 times.
✗ Branch 1 not taken.
2719 name = value->val_str(value, buff, &len);
23590
23591
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2715 times.
2719 if (name == nullptr) {
23592 4 return (1);
23593 }
23594
23595 /* Check if the value is a valid string. */
23596 size_t valid_len;
23597 bool len_error;
23598
3/4
✓ Branch 0 taken 2715 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2711 times.
2715 if (validate_string(system_charset_info, name, len, &valid_len, &len_error)) {
23599 4 return (1);
23600 }
23601
23602 /* monitor_name could point to memory from MySQL
23603 or buff[]. Always dup the name to memory allocated
23604 by InnoDB, so we can access it in another callback
23605 function innodb_monitor_update() and free it appropriately */
23606
1/2
✓ Branch 0 taken 2711 times.
✗ Branch 1 not taken.
2711 if (name) {
23607
1/2
✓ Branch 0 taken 2711 times.
✗ Branch 1 not taken.
2711 monitor_name = my_strdup(PSI_INSTRUMENT_ME, name, MYF(0));
23608 } else {
23609 return (1);
23610 }
23611
23612
1/2
✓ Branch 0 taken 2711 times.
✗ Branch 1 not taken.
2711 ret = innodb_monitor_valid_byname(save, monitor_name);
23613
23614
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 2691 times.
2711 if (ret) {
23615 /* Validation failed */
23616
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 my_free(monitor_name);
23617 } else {
23618 /* monitor_name will be freed in separate callback function
23619 innodb_monitor_update(). Assert "save" point to
23620 the "monitor_name" variable */
23621
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2691 times.
2691 ut_ad(*static_cast<char **>(save) == monitor_name);
23622 }
23623
23624 2711 return (ret);
23625 }
23626
23627 /** Update the system variable innodb_enable(disable/reset/reset_all)_monitor
23628 according to the "set_option" and turn on/off or reset specified monitor
23629 counter. */
23630 2815 static void innodb_monitor_update(
23631 THD *thd, /*!< in: thread handle */
23632 void *var_ptr, /*!< out: where the
23633 formal string goes */
23634 const void *save, /*!< in: immediate result
23635 from check function */
23636 mon_option_t set_option, /*!< in: the set option,
23637 whether to turn on/off or
23638 reset the counter */
23639 bool free_mem) /*!< in: whether we will
23640 need to free the memory */
23641 {
23642 monitor_info_t *monitor_info;
23643 ulint monitor_id;
23644 2815 ulint err_monitor = 0;
23645 const char *name;
23646
23647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2815 times.
2815 ut_a(save != nullptr);
23648
23649 2815 name = *static_cast<const char *const *>(save);
23650
23651
2/2
✓ Branch 0 taken 122 times.
✓ Branch 1 taken 2693 times.
2815 if (!name) {
23652 122 monitor_id = MONITOR_DEFAULT_START;
23653 } else {
23654 2693 monitor_id = innodb_monitor_id_by_name_get(name);
23655
23656 /* Double check we have a valid monitor ID */
23657
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2693 times.
2693 if (monitor_id == MONITOR_NO_MATCH) {
23658 return;
23659 }
23660 }
23661
23662
2/2
✓ Branch 0 taken 122 times.
✓ Branch 1 taken 2693 times.
2815 if (monitor_id == MONITOR_DEFAULT_START) {
23663 /* If user set the variable to "default", we will
23664 print a message and make this set operation a "noop".
23665 The check is being made here is because "set default"
23666 does not go through validation function */
23667
1/2
✓ Branch 0 taken 122 times.
✗ Branch 1 not taken.
122 if (thd) {
23668 122 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_NO_DEFAULT,
23669 "Default value is not defined for"
23670 " this set option. Please specify"
23671 " correct counter or module name.");
23672 } else {
23673 log_errlog(ERROR_LEVEL, ER_INNODB_MONITOR_DEFAULT_VALUE_NOT_DEFINED);
23674 }
23675
23676
1/2
✓ Branch 0 taken 122 times.
✗ Branch 1 not taken.
122 if (var_ptr) {
23677 122 *(const char **)var_ptr = nullptr;
23678 }
23679
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 2640 times.
2693 } else if (monitor_id == MONITOR_WILDCARD_MATCH) {
23680 53 innodb_monitor_update_wildcard(name, set_option);
23681 } else {
23682 2640 monitor_info = srv_mon_get_info(static_cast<monitor_id_t>(monitor_id));
23683
23684
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2640 times.
2640 ut_a(monitor_info);
23685
23686 /* If monitor is already truned on, someone could already
23687 collect monitor data, exit and ask user to turn off the
23688 monitor before turn it on again. */
23689
4/4
✓ Branch 0 taken 2355 times.
✓ Branch 1 taken 285 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2351 times.
2640 if (set_option == MONITOR_TURN_ON && MONITOR_IS_ON(monitor_id)) {
23690 4 err_monitor = monitor_id;
23691 4 goto exit;
23692 }
23693
23694
2/2
✓ Branch 0 taken 2634 times.
✓ Branch 1 taken 2 times.
2636 if (var_ptr) {
23695 2634 *(const char **)var_ptr = monitor_info->monitor_name;
23696 }
23697
23698 /* Depending on the monitor name is for a module or
23699 a counter, process counters in the whole module or
23700 individual counter. */
23701
2/2
✓ Branch 0 taken 231 times.
✓ Branch 1 taken 2405 times.
2636 if (monitor_info->monitor_type & MONITOR_MODULE) {
23702 231 srv_mon_set_module_control(static_cast<monitor_id_t>(monitor_id),
23703 set_option);
23704 } else {
23705 2405 innodb_monitor_set_option(monitor_info, set_option);
23706 }
23707 }
23708 2815 exit:
23709 /* Only if we are trying to turn on a monitor that already
23710 been turned on, we will set err_monitor. Print related
23711 information */
23712
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2811 times.
2815 if (err_monitor) {
23713 4 log_errlog(WARNING_LEVEL, ER_INNODB_MONITOR_IS_ENABLED,
23714 srv_mon_get_name((monitor_id_t)err_monitor));
23715 }
23716
23717
4/4
✓ Branch 0 taken 2813 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2691 times.
✓ Branch 3 taken 122 times.
2815 if (free_mem && name) {
23718 2691 my_free((void *)name);
23719 }
23720
23721 2815 return;
23722 }
23723
23724 /** Validate if passed-in "value" is a valid value for
23725 innodb_buffer_pool_filename. On Windows, file names with colon (:)
23726 are not allowed.
23727 @param[in] thd thread handle
23728 @param[in] save immediate result from update function
23729 @param[in] value incoming string
23730 @return 0 for valid name */
23731 9 static int innodb_srv_buf_dump_filename_validate(THD *thd, SYS_VAR *,
23732 void *save,
23733 struct st_mysql_value *value) {
23734 char buff[OS_FILE_MAX_PATH];
23735 9 int len = sizeof(buff);
23736
23737
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 ut_a(save != nullptr);
23738
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 ut_a(value != nullptr);
23739
23740
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 const char *buf_name = value->val_str(value, buff, &len);
23741
23742
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (buf_name == nullptr) {
23743 return (1);
23744 }
23745
23746
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
9 if (buf_name == buff) {
23747 /* Allocate from thd's memroot */
23748
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 buf_name = thd_strmake(thd, buf_name, len);
23749 }
23750
23751 #ifdef _WIN32
23752 if (is_filename_allowed(buf_name, len, false)) {
23753 *static_cast<const char **>(save) = buf_name;
23754 return (0);
23755 } else {
23756 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
23757 "InnoDB: innodb_buffer_pool_filename"
23758 " cannot have colon (:) in the file name.");
23759 return (1);
23760 }
23761 #else /* _WIN32 */
23762 9 *static_cast<const char **>(save) = buf_name;
23763 9 return (0);
23764 #endif
23765 }
23766
23767 #ifdef UNIV_DEBUG
23768 static char *srv_buffer_pool_evict;
23769
23770 /** Evict all uncompressed pages of compressed tables from the buffer pool.
23771 Keep the compressed pages in the buffer pool.
23772 @return whether all uncompressed pages were evicted */
23773 1847 [[nodiscard]] static bool innodb_buffer_pool_evict_uncompressed(void) {
23774 1847 bool all_evicted = true;
23775
23776
2/2
✓ Branch 0 taken 1847 times.
✓ Branch 1 taken 1847 times.
3694 for (ulint i = 0; i < srv_buf_pool_instances; i++) {
23777 1847 buf_pool_t *buf_pool = &buf_pool_ptr[i];
23778
23779 1847 mutex_enter(&buf_pool->LRU_list_mutex);
23780
23781 1847 for (buf_block_t *block = UT_LIST_GET_LAST(buf_pool->unzip_LRU);
23782
2/2
✓ Branch 0 taken 4855 times.
✓ Branch 1 taken 1847 times.
6702 block != nullptr;) {
23783 4855 buf_block_t *prev_block = UT_LIST_GET_PREV(unzip_LRU, block);
23784
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4855 times.
4855 ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
23785
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4855 times.
4855 ut_ad(block->in_unzip_LRU_list);
23786
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4855 times.
4855 ut_ad(block->page.in_LRU_list);
23787
23788 4855 mutex_enter(&block->mutex);
23789
23790
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4839 times.
4855 if (!buf_LRU_free_page(&block->page, false)) {
23791 16 mutex_exit(&block->mutex);
23792 16 all_evicted = false;
23793 } else {
23794 /* buf_LRU_free_page() released LRU_list_mutex.
23795 have to restart the unzip_LRU scan. */
23796 4839 mutex_enter(&buf_pool->LRU_list_mutex);
23797 4839 block = UT_LIST_GET_LAST(buf_pool->unzip_LRU);
23798 4839 continue;
23799 }
23800 16 block = prev_block;
23801 }
23802
23803 1847 mutex_exit(&buf_pool->LRU_list_mutex);
23804 }
23805
23806 1847 return (all_evicted);
23807 }
23808
23809 /** Called on SET GLOBAL innodb_buffer_pool_evict=...
23810 Handles some values specially, to evict pages from the buffer pool.
23811 SET GLOBAL innodb_buffer_pool_evict='uncompressed'
23812 evicts all uncompressed page frames of compressed tablespaces.
23813 @param[in] save immediate result from check function */
23814 1845 static void innodb_buffer_pool_evict_update(THD *, SYS_VAR *, void *,
23815 const void *save) {
23816
2/2
✓ Branch 0 taken 1844 times.
✓ Branch 1 taken 1 times.
1845 if (const char *op = *static_cast<const char *const *>(save)) {
23817
2/2
✓ Branch 0 taken 1841 times.
✓ Branch 1 taken 3 times.
1844 if (!strcmp(op, "uncompressed")) {
23818
1/2
✓ Branch 0 taken 1847 times.
✗ Branch 1 not taken.
1847 for (uint tries = 0; tries < 10000; tries++) {
23819
2/2
✓ Branch 0 taken 1841 times.
✓ Branch 1 taken 6 times.
1847 if (innodb_buffer_pool_evict_uncompressed()) {
23820 1841 return;
23821 }
23822
23823
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 std::this_thread::sleep_for(std::chrono::milliseconds(10));
23824 }
23825
23826 /* We failed to evict all uncompressed pages. */
23827 ut_d(ut_error);
23828 }
23829 }
23830 }
23831 #endif /* UNIV_DEBUG */
23832
23833 /** Update the system variable innodb_monitor_enable and enable
23834 specified monitor counter.
23835 This function is registered as a callback with MySQL.
23836 @param[in] thd thread handle
23837 @param[out] var_ptr where the formal string goes
23838 @param[in] save immediate result from check function */
23839 2419 static void innodb_enable_monitor_update(THD *thd, SYS_VAR *, void *var_ptr,
23840 const void *save) {
23841 2419 innodb_monitor_update(thd, var_ptr, save, MONITOR_TURN_ON, true);
23842 2419 }
23843
23844 /** Update the system variable innodb_monitor_disable and turn
23845 off specified monitor counter.
23846 @param[in] thd thread handle
23847 @param[out] var_ptr where the formal string goes
23848 @param[in] save immediate result from check function */
23849 179 static void innodb_disable_monitor_update(THD *thd, SYS_VAR *, void *var_ptr,
23850 const void *save) {
23851 179 innodb_monitor_update(thd, var_ptr, save, MONITOR_TURN_OFF, true);
23852 179 }
23853
23854 /** Update the system variable innodb_monitor_reset and reset
23855 specified monitor counter(s).
23856 This function is registered as a callback with MySQL.
23857 @param[in] thd thread handle
23858 @param[out] var_ptr where the formal string goes
23859 @param[in] save immediate result from check function */
23860 123 static void innodb_reset_monitor_update(THD *thd, SYS_VAR *, void *var_ptr,
23861 const void *save) {
23862 123 innodb_monitor_update(thd, var_ptr, save, MONITOR_RESET_VALUE, true);
23863 123 }
23864
23865 /** Update the system variable innodb_monitor_reset_all and reset
23866 all value related monitor counter.
23867 This function is registered as a callback with MySQL.
23868 @param[in] thd thread handle
23869 @param[out] var_ptr where the formal string goes
23870 @param[in] save immediate result from check function */
23871 92 static void innodb_reset_all_monitor_update(THD *thd, SYS_VAR *, void *var_ptr,
23872 const void *save) {
23873 92 innodb_monitor_update(thd, var_ptr, save, MONITOR_RESET_ALL_VALUE, true);
23874 92 }
23875
23876 /** Validate the value of innodb_undo_tablespaces global variable. This function
23877 is registered as a callback with MySQL.
23878 @param[in] thd thread handle
23879 @param[in] var pointer to system variable
23880 @param[in] var_ptr where the formal string goes
23881 @param[in] save immediate result from check function */
23882 6 static void innodb_undo_tablespaces_update(THD *thd [[maybe_unused]],
23883 SYS_VAR *var [[maybe_unused]],
23884 void *var_ptr [[maybe_unused]],
23885 const void *save [[maybe_unused]]) {
23886 6 innodb_undo_tablespaces_deprecate();
23887 6 }
23888
23889 /** Validate the value of innodb_parallel_doublewrite_path global variable.
23890 This function is registered as a callback with MySQL.
23891 @param[in] thd thread handle
23892 @param[in] var pointer to system variable
23893 @param[in] var_ptr where the formal string goes
23894 @param[in] save immediate result from check function */
23895 static void innodb_parallel_doublewrite_path_update(
23896 THD *thd [[maybe_unused]], SYS_VAR *var [[maybe_unused]],
23897 void *var_ptr [[maybe_unused]],
23898 const void *save [[maybe_unused]]) {
23899 innodb_parallel_doublewrite_path_deprecate();
23900 }
23901
23902 /** Validate the value of innodb_parallel_dblwr_encrypt global variable.
23903 This function is registered as a callback with MySQL.
23904 @param[in] thd thread handle
23905 @param[in] var pointer to system variable
23906 @param[in] var_ptr where the formal string goes
23907 @param[in] save immediate result from check function */
23908 3 static void innodb_parallel_dblwr_encrypt_update(
23909 THD *thd [[maybe_unused]], SYS_VAR *var [[maybe_unused]],
23910 void *var_ptr [[maybe_unused]],
23911 const void *save [[maybe_unused]]) {
23912 3 innodb_parallel_dblwr_encrypt_deprecate();
23913 3 }
23914
23915 /* Declare default check function for boolean system variable. Cannot include
23916 sql_plugin_var.h header in this file due to conflicting macro definitions. */
23917 int check_func_bool(THD *, SYS_VAR *, void *save, st_mysql_value *value);
23918
23919 /** Validate the value of innodb_undo_log_encrypt global variable. This function
23920 is registered as a callback with MySQL.
23921 @param[in] thd thread handle
23922 @param[in] var pointer to system variable
23923 @param[in] save possibly updated variable value
23924 @param[in] value current variable value
23925 @return error code */
23926 105 static int validate_innodb_undo_log_encrypt(THD *thd, SYS_VAR *var, void *save,
23927 struct st_mysql_value *value) {
23928 /* Call the default check function first. */
23929 105 auto error = check_func_bool(thd, var, save, value);
23930
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 102 times.
105 if (error != 0) {
23931 3 return (error);
23932 }
23933 102 bool target = *static_cast<bool *>(save);
23934
23935 /* Set the default output to current value for all error cases. */
23936 102 *static_cast<bool *>(save) = srv_undo_log_encrypt;
23937
23938
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 57 times.
102 if (srv_undo_log_encrypt == target) {
23939 /* No change */
23940 45 return (0);
23941 }
23942
23943
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 13 times.
57 if (target) {
23944
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (Encryption::is_online_encryption_on()) {
23945 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
23946 "Undo log cannot be"
23947 " encrypted with Master Key encryption"
23948 " when online to KEYRING encryption is turned ON.");
23949 return 1;
23950 }
23951 }
23952
23953 /* If encryption is to be disabled. This will just make sure I/O doesn't
23954 write UNDO pages encrypted from now on. */
23955
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 44 times.
57 if (target == false) {
23956 13 *static_cast<bool *>(save) = false;
23957 13 return (0);
23958 }
23959
23960 /* There would be at least 2 UNDO tablespaces */
23961
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 ut_ad(undo::spaces->size() >= FSP_IMPLICIT_UNDO_TABLESPACES);
23962
23963
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 39 times.
44 if (!Encryption::check_keyring()) {
23964 5 ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_DA_UNDO_NO_KEYRING);
23965 5 ib::error(ER_UNDO_NO_KEYRING);
23966 5 return (0);
23967 }
23968
23969
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (srv_read_only_mode) {
23970 ib::error(ER_IB_MSG_1051);
23971 ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_IB_MSG_1051);
23972 return (0);
23973 }
23974
23975 /* UNDO tablespace encryption to be mutually exclusive with any UNDO DDL */
23976 39 mutex_enter(&undo::ddl_mutex);
23977
23978 /* Enable encryption for UNDO tablespaces */
23979 39 bool ret = srv_enable_undo_encryption(nullptr);
23980
23981
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 2 times.
39 if (!ret) {
23982 /* At this point, all UNDO tablespaces have been encrypted. */
23983 37 *static_cast<bool *>(save) = true;
23984 }
23985
23986 39 mutex_exit(&undo::ddl_mutex);
23987 39 return (0);
23988 }
23989
23990 /** Validate the value of innodb_redo_log_encrypt global variable. This function
23991 is registered as a callback with MySQL.
23992 @param[in] thd thread handle
23993 @param[in] var pointer to system variable
23994 @param[in] save possibly updated variable value
23995 @param[in] value current variable value
23996 @return error code */
23997 110 static int validate_innodb_redo_log_encrypt(THD *thd, SYS_VAR *var, void *save,
23998 struct st_mysql_value *value) {
23999 /* Call the default check function first. */
24000 110 auto error = check_func_bool(thd, var, save, value);
24001
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 107 times.
110 if (error != 0) {
24002 3 return (error);
24003 }
24004 107 bool target = *static_cast<bool *>(save);
24005
24006 /* Set the default output to current value for all error cases. */
24007 107 *static_cast<bool *>(save) = srv_redo_log_encrypt;
24008
24009
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 50 times.
107 if (srv_redo_log_encrypt == target) {
24010 /* No change */
24011 57 return (0);
24012 }
24013
24014 /* If encryption is to be disabled. This will just make sure I/O doesn't
24015 write REDO encrypted from now on. */
24016
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 37 times.
50 if (target == false) {
24017 13 *static_cast<bool *>(save) = false;
24018 13 return (0);
24019 }
24020
24021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 if (srv_read_only_mode) {
24022 ib::error(ER_IB_MSG_LOG_FILES_CANNOT_ENCRYPT_IN_READ_ONLY);
24023 return (0);
24024 }
24025
24026 /* Enable encryption for REDO tablespaces */
24027 37 bool ret = srv_enable_redo_encryption();
24028
24029
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 7 times.
37 if (!ret) {
24030 /* At this point, REDO log is set to be encrypted. */
24031 30 *static_cast<bool *>(save) = true;
24032 }
24033 37 return (0);
24034 }
24035
24036 9 static int innodb_sys_tablespace_encyption_validate(
24037 THD *thd, SYS_VAR *var, void *save, struct st_mysql_value *value) {
24038 const char *innodb_sys_tablespace_encryption_input;
24039 char buff[STRING_BUFFER_USUAL_SIZE];
24040 9 int len = sizeof(buff);
24041
24042
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 ut_a(save != nullptr);
24043
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 ut_a(value != nullptr);
24044
24045
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 innodb_sys_tablespace_encryption_input = value->val_str(value, buff, &len);
24046
24047 9 bool legit_value = false;
24048 9 uint use = 0;
24049 // The last item of sys_tablespace_encrypt_names is nullptr
24050 9 const size_t encrypt_names_cnt =
24051 array_elements(sys_tablespace_encrypt_names) - 1;
24052
24053
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 5 times.
27 for (; use < encrypt_names_cnt; use++) {
24054
3/4
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 18 times.
22 if (!innobase_strcasecmp(innodb_sys_tablespace_encryption_input,
24055 sys_tablespace_encrypt_names[use])) {
24056 4 legit_value = true;
24057 4 break;
24058 }
24059 }
24060 // It is possible that enum value was provided as the integer, not literal
24061
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
9 if (!legit_value) {
24062 5 int error = 0;
24063
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 use = (uint)my_strtoll10(innodb_sys_tablespace_encryption_input, nullptr,
24064 &error);
24065
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
5 if (!error && use < encrypt_names_cnt) {
24066 2 legit_value = true;
24067 }
24068 }
24069
24070
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 6 times.
9 if (!legit_value) return 1;
24071
24072 6 const auto change_to_sys_tablespace_encryption =
24073 static_cast<srv_sys_tablespace_encrypt_enum>(use);
24074
24075
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (change_to_sys_tablespace_encryption == SYS_TABLESPACE_ENCRYPT_OFF) {
24076
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (srv_sys_tablespace_encrypt == SYS_TABLESPACE_ENCRYPT_ON) {
24077 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
24078 "System tablespace Master Key encryption cannot be "
24079 "turned OFF dynamically. "
24080 "However you can still re-encrypt system tablespace "
24081 "with encryption threads "
24082 "and then instruct encryption threads to decrypt the "
24083 "system tablespace.");
24084 return 1;
24085 }
24086
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (srv_sys_tablespace_encrypt == SYS_TABLESPACE_RE_ENCRYPTING_TO_KEYRING) {
24087 push_warning_printf(
24088 thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
24089 "RE_ENCRYPTING_TO_KEYRING can be only used when system tablespace "
24090 "was previously encrypted with Master Key encryption. To encrypt "
24091 "system tablespace with KEYRING encryption please use encryption "
24092 "threads.");
24093 return 1;
24094 }
24095 }
24096
24097
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (change_to_sys_tablespace_encryption == SYS_TABLESPACE_ENCRYPT_ON) {
24098
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (srv_sys_tablespace_encrypt == SYS_TABLESPACE_ENCRYPT_OFF) {
24099
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 push_warning_printf(
24100 thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
24101 "System tablespace Master Key encryption can be turned ON only "
24102 "at bootstrap. You can still encrypt System tablespace encryption "
24103 "with "
24104 "KEYRING encryption.");
24105 2 return 1;
24106 } else if (srv_sys_tablespace_encrypt ==
24107 SYS_TABLESPACE_RE_ENCRYPTING_TO_KEYRING) {
24108 // The system tablespace encryption was marked to be re-encrypted to
24109 // keyring. We allow it to be set back to ON in case encryption threads
24110 // were not yet activated and system tablespace remain encrypted with
24111 // Master Key.
24112 if (Encryption::is_online_encryption_on()) {
24113 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
24114 "System tablespace cannot be marked as encrypted "
24115 "with Master Key encryption "
24116 "when Online to keyring encryption is turned ON or "
24117 "when system tablespace "
24118 "was already encrypted with KEYRING encryption.");
24119 return 1;
24120 } else {
24121 fil_space_t *space = fil_space_acquire_silent(TRX_SYS_SPACE);
24122 ut_ad(space != nullptr);
24123 fil_space_crypt_t *crypt_data = space->crypt_data;
24124 fil_space_release(space);
24125
24126 if (crypt_data != nullptr) {
24127 push_warning_printf(thd, Sql_condition::SL_WARNING,
24128 ER_WRONG_ARGUMENTS,
24129 "System tablespace cannot be marked as encrypted "
24130 "with Master Key encryption "
24131 "as it was already encrypted with KEYRING "
24132 "encryption and Master Key encryption "
24133 "is bootstrap only option.");
24134 return 1;
24135 }
24136 }
24137 }
24138 }
24139
24140
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (change_to_sys_tablespace_encryption ==
24141 1 SYS_TABLESPACE_RE_ENCRYPTING_TO_KEYRING &&
24142
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 srv_sys_tablespace_encrypt == SYS_TABLESPACE_ENCRYPT_OFF) {
24143
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 push_warning_printf(
24144 thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
24145 "System tablespace can only be marked to be re-encrypted with keyring "
24146 "in "
24147 "case it was previosly encrypted with Master Key encryption. "
24148 "You still can encrypt unencrypted system tablespace with encryption "
24149 "threads.");
24150 1 return 1;
24151 }
24152
24153 3 *static_cast<ulong *>(save) = use;
24154
24155 3 return 0;
24156 }
24157
24158 /** Update the number of rollback segments per tablespace when the
24159 system variable innodb_rollback_segments is changed.
24160 This function is registered as a callback with MySQL.
24161 @param[in] save immediate result from check function */
24162 22 static void innodb_rollback_segments_update(THD *, SYS_VAR *, void *,
24163 const void *save) {
24164 22 ulong target = *static_cast<const ulong *>(save);
24165
24166
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 15 times.
22 if (srv_rollback_segments == target) {
24167 11 return;
24168 }
24169
24170
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 13 times.
15 if (srv_read_only_mode) {
24171
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 ib::warn(ER_IB_MSG_578) << "Cannot set innodb_rollback_segments to "
24172
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 << target << " when in read-only mode";
24173 2 return;
24174 }
24175
24176
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11 times.
13 if (srv_force_recovery > 0) {
24177
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 ib::warn(ER_IB_MSG_579) << "Cannot set innodb_rollback_segments to "
24178
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 << target << " when in innodb_force_recovery > 0";
24179 2 return;
24180 }
24181
24182 /* Serialize this adjustment with all undo tablespace DDLs. */
24183
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 mutex_enter(&undo::ddl_mutex);
24184
24185
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
11 if (!trx_rseg_adjust_rollback_segments(target)) {
24186 ib::warn(ER_IB_MSG_580)
24187 << "Failed to set innodb_rollback_segments to " << target;
24188 return;
24189 }
24190
24191 11 srv_rollback_segments = target;
24192
24193
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 mutex_exit(&undo::ddl_mutex);
24194 }
24195
24196 /** Parse and enable InnoDB monitor counters during server startup.
24197 User can list the monitor counters/groups to be enable by specifying
24198 "loose-innodb_monitor_enable=monitor_name1;monitor_name2..."
24199 in server configuration file or at the command line. The string
24200 separate could be ";", "," or empty space. */
24201 2 static void innodb_enable_monitor_at_startup(
24202 char *str) /*!< in/out: monitor counter enable list */
24203 {
24204 static const char *sep = " ;,";
24205 char *last;
24206
24207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 ut_a(str);
24208
24209 /* Walk through the string, and separate each monitor counter
24210 and/or counter group name, and calling innodb_monitor_update()
24211 if successfully updated. Please note that the "str" would be
24212 changed by strtok_r() as it walks through it. */
24213
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (char *option = my_strtok_r(str, sep, &last); option;
24214 2 option = my_strtok_r(nullptr, sep, &last)) {
24215 ulint ret;
24216 char *option_name;
24217
24218
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 ret = innodb_monitor_valid_byname(&option_name, option);
24219
24220 /* The name is validated if ret == 0 */
24221
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!ret) {
24222
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 innodb_monitor_update(nullptr, nullptr, &option, MONITOR_TURN_ON, false);
24223 } else {
24224 log_errlog(WARNING_LEVEL, ER_INNODB_INVALID_MONITOR_COUNTER_NAME, option);
24225 }
24226 }
24227 2 }
24228
24229 #if defined(UNIV_LINUX) && (defined(UNIV_DEBUG) || defined(UNIV_PERF_DEBUG))
24230
24231 /** Update the innodb_sched_priority_purge variable and set the thread
24232 priorities accordingly.
24233 @param[in] thd thread handle
24234 @param[in] var pointer to system variable
24235 @param[out] var_ptr where the formal string goes
24236 @param[in] save immediate result from check function */
24237 8 static void innodb_sched_priority_purge_update(THD *thd, SYS_VAR *var,
24238 void *var_ptr,
24239 const void *save) {
24240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (srv_read_only_mode) return;
24241
24242 8 const ulint priority = *static_cast<const ulint *>(save);
24243
24244
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 8 times.
40 for (ulint i = 0; i < srv_n_purge_threads; i++) {
24245 const ulint actual_priority =
24246 32 os_thread_set_priority(srv_purge_tids[i], priority);
24247
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (UNIV_UNLIKELY(actual_priority != priority)) {
24248 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
24249 "Failed to set the purge thread priority to %lu, "
24250 "the current priority is %lu, aborting priority "
24251 "update",
24252 priority, actual_priority);
24253 return;
24254 }
24255 }
24256
24257 8 srv_sched_priority_purge = priority;
24258 }
24259
24260 /** Update the innodb_sched_priority_io variable and set the thread priorities
24261 accordingly.
24262 @param[in] thd thread handle
24263 @param[in] var pointer to system variable
24264 @param[out] var_ptr where the formal string goes
24265 @param[in] save immediate result from check function */
24266 7 static void innodb_sched_priority_io_update(THD *thd, SYS_VAR *var,
24267 void *var_ptr, const void *save) {
24268 7 const ulint priority = *static_cast<const ulint *>(save);
24269
24270
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 7 times.
77 for (ulint i = 0; i < srv_n_file_io_threads; i++) {
24271 const ulint actual_priority =
24272 70 os_thread_set_priority(srv_io_tids[i], priority);
24273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
70 if (UNIV_UNLIKELY(actual_priority != priority)) {
24274 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
24275 "Failed to set the I/O thread priority to %lu, the "
24276 "current priority is %lu, aborting priority update",
24277 priority, actual_priority);
24278 return;
24279 }
24280 }
24281 7 srv_sched_priority_io = priority;
24282 }
24283
24284 /** Update the innodb_sched_priority_master variable and set the thread
24285 priorities accordingly.
24286 @param[in] thd thread handle
24287 @param[in] var pointer to system variable
24288 @param[out] var_ptr where the formal string goes
24289 @param[in] save immediate result from check function */
24290 7 static void innodb_sched_priority_master_update(THD *thd, SYS_VAR *var,
24291 void *var_ptr,
24292 const void *save) {
24293
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (srv_read_only_mode) return;
24294
24295 7 const ulint priority = *static_cast<const lint *>(save);
24296 const ulint actual_priority =
24297 7 os_thread_set_priority(srv_master_tid, priority);
24298
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (UNIV_UNLIKELY(actual_priority != priority)) {
24299 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
24300 "Failed to set the master thread priority to %lu, the "
24301 "current priority is %lu",
24302 priority, actual_priority);
24303 } else {
24304 7 srv_sched_priority_master = priority;
24305 }
24306 }
24307
24308 #endif /* defined(UNIV_LINUX) && (defined(UNIV_DEBUG) || \
24309 defined(UNIV_PERF_DEBUG)) */
24310
24311 /** Callback function for accessing the InnoDB variables from MySQL:
24312 SHOW VARIABLES. */
24313 142028 static int show_innodb_vars(THD *, SHOW_VAR *var, char *) {
24314 142028 innodb_export_status();
24315 142027 var->type = SHOW_ARRAY;
24316 142027 var->value = (char *)&innodb_status_variables;
24317 142027 var->scope = SHOW_SCOPE_GLOBAL;
24318
24319 142027 return (0);
24320 }
24321
24322 /** This function checks each index name for a table against reserved
24323 system default primary index name 'GEN_CLUST_INDEX'. If a name
24324 matches, this function pushes an warning message to the client,
24325 and returns true.
24326 @return true if the index name matches the reserved name */
24327 385055 bool innobase_index_name_is_reserved(
24328 THD *thd, /*!< in/out: MySQL connection */
24329 const KEY *key_info, /*!< in: Indexes to be created */
24330 ulint num_of_keys) /*!< in: Number of indexes to
24331 be created. */
24332 {
24333 const KEY *key;
24334 uint key_num; /* index number */
24335
24336
2/2
✓ Branch 0 taken 234265 times.
✓ Branch 1 taken 385052 times.
619317 for (key_num = 0; key_num < num_of_keys; key_num++) {
24337 234265 key = &key_info[key_num];
24338
24339
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 234262 times.
234265 if (innobase_strcasecmp(key->name, innobase_index_reserve_name) == 0) {
24340 /* Push warning to mysql */
24341 3 push_warning_printf(thd, Sql_condition::SL_WARNING,
24342 ER_WRONG_NAME_FOR_INDEX,
24343 "Cannot Create Index with name"
24344 " '%s'. The name is reserved"
24345 " for the system default primary"
24346 " index.",
24347 innobase_index_reserve_name);
24348
24349 3 my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), innobase_index_reserve_name);
24350
24351 3 return (true);
24352 }
24353 }
24354
24355 385052 return (false);
24356 }
24357
24358 /** Retrieve the FTS Relevance Ranking result for doc with doc_id
24359 of m_prebuilt->fts_doc_id
24360 @param[in,out] fts_hdl FTS handler
24361 @return the relevance ranking value */
24362 36908 static float innobase_fts_retrieve_ranking(FT_INFO *fts_hdl) {
24363 fts_result_t *result;
24364 row_prebuilt_t *ft_prebuilt [[maybe_unused]];
24365
24366 36908 result = reinterpret_cast<NEW_FT_INFO *>(fts_hdl)->ft_result;
24367
24368 36908 ft_prebuilt = reinterpret_cast<NEW_FT_INFO *>(fts_hdl)->ft_prebuilt;
24369
24370 36908 fts_ranking_t *ranking = rbt_value(fts_ranking_t, result->current);
24371
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36908 times.
36908 assert(ft_prebuilt->fts_doc_id == ranking->doc_id);
24372
24373 36908 return (ranking->rank);
24374 }
24375
24376 /** Free the memory for the FTS handler
24377 @param[in,out] fts_hdl FTS handler */
24378 2288 static void innobase_fts_close_ranking(FT_INFO *fts_hdl) {
24379 fts_result_t *result;
24380
24381 2288 result = reinterpret_cast<NEW_FT_INFO *>(fts_hdl)->ft_result;
24382
24383 2288 fts_query_free_result(result);
24384
24385 2288 my_free((uchar *)fts_hdl);
24386 2288 }
24387
24388 /** Find and Retrieve the FTS Relevance Ranking result for doc with doc_id
24389 of m_prebuilt->fts_doc_id
24390 @param[in,out] fts_hdl FTS handler
24391 @return the relevance ranking value */
24392 5696 static float innobase_fts_find_ranking(FT_INFO *fts_hdl, uchar *, uint) {
24393 fts_result_t *result;
24394 row_prebuilt_t *ft_prebuilt;
24395
24396 5696 ft_prebuilt = reinterpret_cast<NEW_FT_INFO *>(fts_hdl)->ft_prebuilt;
24397 5696 result = reinterpret_cast<NEW_FT_INFO *>(fts_hdl)->ft_result;
24398
24399 /* Retrieve the ranking value for doc_id with value of
24400 m_prebuilt->fts_doc_id */
24401 5696 return (fts_retrieve_ranking(result, ft_prebuilt->fts_doc_id));
24402 }
24403
24404 #ifdef UNIV_DEBUG
24405 static bool innodb_background_drop_list_empty = true;
24406 static bool innodb_purge_run_now = true;
24407 static bool innodb_purge_stop_now = true;
24408 static bool innodb_log_checkpoint_now = true;
24409 static bool innodb_log_checkpoint_fuzzy_now = true;
24410 static bool innodb_log_flush_now = true;
24411 static bool innodb_buf_flush_list_now = true;
24412
24413 static uint innodb_merge_threshold_set_all_debug =
24414 DICT_INDEX_MERGE_THRESHOLD_DEFAULT;
24415
24416 /** Wait for the background drop list to become empty. */
24417 4 static void wait_background_drop_list_empty(THD *, SYS_VAR *, void *,
24418 const void *) {
24419 4 row_wait_for_background_drop_list_empty();
24420 4 }
24421
24422 /** Set the purge state to RUN. If purge is disabled then it
24423 is a no-op. This function is registered as a callback with MySQL.
24424 @param[in] save immediate result from check function */
24425 387 static void purge_run_now_set(THD *, SYS_VAR *, void *, const void *save) {
24426
5/6
✓ Branch 0 taken 384 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 384 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 384 times.
✓ Branch 5 taken 3 times.
387 if (*(bool *)save && trx_purge_state() != PURGE_STATE_DISABLED) {
24427 384 trx_purge_run();
24428 }
24429 387 }
24430
24431 /** Set the purge state to STOP. If purge is disabled then it
24432 is a no-op. This function is registered as a callback with MySQL.
24433 @param[in] save immediate result from check function */
24434 102 static void purge_stop_now_set(THD *, SYS_VAR *, void *, const void *save) {
24435
5/6
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 97 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 97 times.
✓ Branch 5 taken 5 times.
102 if (*(bool *)save && trx_purge_state() != PURGE_STATE_DISABLED) {
24436 97 trx_purge_stop();
24437 }
24438 102 }
24439
24440 /** Force InnoDB to flush redo log up to current_lsn.
24441 This function is registered as a callback with MySQL.
24442 @param[in] save immediate result from check function */
24443 8 static void log_flush_now_set(THD *, SYS_VAR *, void *, const void *save) {
24444
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 if (!*(bool *)save) {
24445 6 return;
24446 }
24447
24448 2 log_buffer_flush_to_disk(true);
24449 }
24450
24451 /** Force InnoDB to do sharp checkpoint. This forces a flush of all
24452 dirty pages.
24453 @param[in] save immediate result from check function */
24454 31 static void checkpoint_now_set(THD *, SYS_VAR *, void *, const void *save) {
24455
3/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
31 if (*(bool *)save && !srv_checkpoint_disabled) {
24456 /* Note that it's defined only when UNIV_DEBUG is defined.
24457 It seems to be very risky feature. Fortunately it is used
24458 only inside mtr tests. */
24459
24460
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 24 times.
97 while (log_make_latest_checkpoint(*log_sys)) {
24461 /* Creating checkpoint could itself result in
24462 new log records. Hence we repeat until:
24463 last_checkpoint_lsn = log_get_lsn(). */
24464 }
24465
24466 48 dberr_t err = fil_write_flushed_lsn(log_sys->last_checkpoint_lsn.load());
24467
24468
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 ut_a(err == DB_SUCCESS);
24469 }
24470 31 }
24471
24472 /** Force InnoDB to do fuzzy checkpoint. Fuzzy checkpoint does not
24473 force InnoDB to flush dirty pages. It only forces to write the new
24474 checkpoint_lsn to the header of the log file containing that LSN.
24475 This LSN is where the recovery starts. You can read more about the
24476 fuzzy checkpoints in the internet.
24477 @param[in] save immediate result from check function */
24478 8 static void checkpoint_fuzzy_now_set(THD *, SYS_VAR *, void *,
24479 const void *save) {
24480
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
8 if (*(bool *)save && !srv_checkpoint_disabled) {
24481 /* Note that it's defined only when UNIV_DEBUG is defined.
24482 It seems to be very risky feature. Fortunately it is used
24483 only inside mtr tests. */
24484
24485 2 log_request_checkpoint(*log_sys, true);
24486 }
24487 8 }
24488
24489 /** Updates srv_checkpoint_disabled - allowing or disallowing checkpoints.
24490 This is called when user invokes SET GLOBAL innodb_checkpoints_disabled=0/1.
24491 After checkpoints are disabled, there will be no write of a checkpoint,
24492 until checkpoints are re-enabled (log_sys->checkpointer_mutex protects that)
24493 @param[in] save immediate result from check function */
24494 94 static void checkpoint_disabled_update(THD *, SYS_VAR *, void *,
24495 const void *save) {
24496 /* We need to acquire the checkpointer_mutex, to ensure that
24497 after we have finished this function, there will be no new
24498 checkpoint written (e.g. in case there is currently curring
24499 checkpoint). When checkpoint is being written, the same mutex
24500 is acquired, current value of srv_checkpoint_disabled is checked,
24501 and if checkpoints are disabled, we cancel writing the checkpoint. */
24502
24503 94 log_t &log = *log_sys;
24504
24505 94 log_checkpointer_mutex_enter(log);
24506 94 log_limits_mutex_enter(log);
24507
24508 94 srv_checkpoint_disabled = *static_cast<const bool *>(save);
24509
24510 94 log_limits_mutex_exit(log);
24511 94 log_checkpointer_mutex_exit(log);
24512 94 }
24513
24514 /** Force a dirty pages flush now.
24515 @param[in] save immediate result from check function */
24516 200 static void buf_flush_list_now_set(THD *, SYS_VAR *, void *, const void *save) {
24517
2/2
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 5 times.
200 if (*(bool *)save) {
24518 195 buf_flush_sync_all_buf_pools();
24519 }
24520 200 }
24521
24522 /** Override current MERGE_THRESHOLD setting for all indexes at dictionary
24523 now.
24524 @param[in] save immediate result from check function */
24525 7 static void innodb_merge_threshold_set_all_debug_update(THD *, SYS_VAR *,
24526 void *,
24527 const void *save) {
24528 7 innodb_merge_threshold_set_all_debug = (*static_cast<const uint *>(save));
24529 7 dict_set_merge_threshold_all_debug(innodb_merge_threshold_set_all_debug);
24530 7 }
24531
24532 #endif /* UNIV_DEBUG */
24533
24534 /** Find and Retrieve the FTS doc_id for the current result row
24535 @param[in,out] fts_hdl FTS handler
24536 @return the document ID */
24537 static ulonglong innobase_fts_retrieve_docid(FT_INFO_EXT *fts_hdl) {
24538 fts_result_t *result;
24539 row_prebuilt_t *ft_prebuilt;
24540
24541 ft_prebuilt = reinterpret_cast<NEW_FT_INFO *>(fts_hdl)->ft_prebuilt;
24542 result = reinterpret_cast<NEW_FT_INFO *>(fts_hdl)->ft_result;
24543
24544 if (ft_prebuilt->read_just_key) {
24545 fts_ranking_t *ranking = rbt_value(fts_ranking_t, result->current);
24546
24547 return (ranking->doc_id);
24548 }
24549
24550 return (ft_prebuilt->fts_doc_id);
24551 }
24552
24553 /* These variables are never read by InnoDB or changed. They are a kind of
24554 dummies that are needed by the MySQL infrastructure to call
24555 buffer_pool_dump_now(), buffer_pool_load_now() and buffer_pool_load_abort()
24556 by the user by doing:
24557 SET GLOBAL innodb_buffer_pool_dump_now=ON;
24558 SET GLOBAL innodb_buffer_pool_load_now=ON;
24559 SET GLOBAL innodb_buffer_pool_load_abort=ON;
24560 Their values are read by MySQL and displayed to the user when the variables
24561 are queried, e.g.:
24562 SELECT @@innodb_buffer_pool_dump_now;
24563 SELECT @@innodb_buffer_pool_load_now;
24564 SELECT @@innodb_buffer_pool_load_abort; */
24565 static bool innodb_buffer_pool_dump_now = false;
24566 static bool innodb_buffer_pool_load_now = false;
24567 static bool innodb_buffer_pool_load_abort = false;
24568
24569 /** Trigger a dump of the buffer pool if innodb_buffer_pool_dump_now is set
24570 to ON. This function is registered as a callback with MySQL.
24571 @param[in] save immediate result from check function */
24572 10 static void buffer_pool_dump_now(THD *, SYS_VAR *, void *, const void *save) {
24573
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
10 if (*(bool *)save && !srv_read_only_mode) {
24574 7 buf_dump_start();
24575 }
24576 10 }
24577
24578 /** Trigger a load of the buffer pool if innodb_buffer_pool_load_now is set
24579 to ON. This function is registered as a callback with MySQL.
24580 @param[in] save immediate result from check function */
24581 9 static void buffer_pool_load_now(THD *, SYS_VAR *, void *, const void *save) {
24582
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
9 if (*(bool *)save) {
24583 6 buf_load_start();
24584 }
24585 9 }
24586
24587 /** Abort a load of the buffer pool if innodb_buffer_pool_load_abort
24588 is set to ON. This function is registered as a callback with MySQL.
24589 @param[in] save immediate result from check function */
24590 4 static void buffer_pool_load_abort(THD *, SYS_VAR *, void *, const void *save) {
24591
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (*(bool *)save) {
24592 1 buf_load_abort();
24593 }
24594 4 }
24595
24596 /** Update the system variable innodb_log_write_ahead_size using the "saved"
24597 value. This function is registered as a callback with MySQL.
24598 @param[in] thd thread handle
24599 @param[in] save immediate result from check function */
24600 163 static void innodb_log_write_ahead_size_update(THD *thd, SYS_VAR *, void *,
24601 const void *save) {
24602 163 ulong val = INNODB_LOG_WRITE_AHEAD_SIZE_MIN;
24603 163 ulong in_val = *static_cast<const ulong *>(save);
24604
24605
2/2
✓ Branch 0 taken 424 times.
✓ Branch 1 taken 163 times.
587 while (val < in_val) {
24606 424 val = val * 2;
24607 }
24608
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 163 times.
163 if (val > INNODB_LOG_WRITE_AHEAD_SIZE_MAX) {
24609 val = INNODB_LOG_WRITE_AHEAD_SIZE_MAX;
24610 }
24611
24612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 163 times.
163 if (val > UNIV_PAGE_SIZE) {
24613 val = UNIV_PAGE_SIZE;
24614 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
24615 "innodb_log_write_ahead_size cannot"
24616 " be set higher than innodb_page_size.");
24617
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 162 times.
163 } else if (val != in_val) {
24618 1 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
24619 "innodb_log_write_ahead_size should be"
24620 " set to power of 2, in range [%lu,%lu]",
24621 INNODB_LOG_WRITE_AHEAD_SIZE_MIN,
24622 INNODB_LOG_WRITE_AHEAD_SIZE_MAX);
24623 }
24624
24625
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 162 times.
163 if (val != in_val) {
24626 1 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
24627 "Setting innodb_log_write_ahead_size"
24628 " to %lu",
24629 val);
24630 }
24631
24632 163 log_write_ahead_resize(*log_sys, val);
24633 163 }
24634
24635 /** Update the system variable innodb_log_buffer_size using the "saved"
24636 value. This function is registered as a callback with MySQL.
24637 @param[in] save immediate result from check function */
24638 165 static void innodb_log_buffer_size_update(THD *, SYS_VAR *, void *,
24639 const void *save) {
24640 165 const ulong val = *static_cast<const ulong *>(save);
24641
24642
3/6
✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 165 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 165 times.
✗ Branch 5 not taken.
165 ib::info(ER_IB_MSG_1255) << "Setting innodb_log_buffer_size to " << val;
24643
24644
2/4
✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 165 times.
165 if (!log_buffer_resize(*log_sys, val)) {
24645 /* This could happen if we tried to decrease size of the
24646 log buffer but we had more data in the log buffer than
24647 the new size. We could have asked for writing the data to
24648 disk, after x-locking the log buffer, but this could lead
24649 to deadlock if there was no space in log files and checkpoint
24650 was required (because checkpoint writes new redo records
24651 when persisting dd table buffer). That's why we don't ask
24652 for writing to disk. */
24653
24654 ib::error(ER_IB_MSG_1256) << "Failed to change size of the log buffer."
24655 " Try flushing the log buffer first.";
24656 }
24657 165 }
24658
24659 /** Update the innodb_log_writer_threads parameter.
24660 @param[out] var_ptr current value
24661 @param[in] save immediate result from check function */
24662 6 static void innodb_log_writer_threads_update(THD *, SYS_VAR *, void *var_ptr,
24663 const void *save) {
24664 6 *static_cast<bool *>(var_ptr) = *static_cast<const bool *>(save);
24665
24666 /* pause/resume the log writer threads based on innodb_log_writer_threads
24667 value. */
24668 6 log_control_writer_threads(*log_sys);
24669 6 }
24670
24671 /** Update the system variable innodb_redo_log_capacity using the "saved"
24672 value. This function is registered as a callback with MySQL.
24673 @param[in] thd thread handle
24674 @param[in] save immediate result from check function */
24675 10 static void innodb_redo_log_capacity_update(THD *thd, SYS_VAR *, void *,
24676 const void *save) {
24677 10 const auto new_value = *static_cast<const ulonglong *>(save);
24678
24679
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 ut_a(LOG_CAPACITY_MIN <= new_value);
24680
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 ut_a(new_value <= LOG_CAPACITY_MAX);
24681
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 ut_a(new_value % MB == 0);
24682
24683 10 srv_redo_log_capacity = new_value;
24684
24685
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6 times.
10 if (new_value == srv_redo_log_capacity_used) {
24686 4 return;
24687 }
24688
24689 6 srv_redo_log_capacity_used = new_value;
24690
24691 6 ib::info(ER_IB_MSG_LOG_FILES_CAPACITY_CHANGED,
24692
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 srv_redo_log_capacity_used / MB);
24693
24694 6 log_files_resize_requested(*log_sys);
24695
24696
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!log_sys->concurrency_margin_is_safe.load()) {
24697 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
24698 "Current innodb_redo_log_capacity"
24699 " is too small for safety of redo log files."
24700 " Consider increasing it or decreasing"
24701 " innodb_thread_concurrency.");
24702 }
24703 }
24704
24705 /** Update the system variable innodb_thread_concurrency using the "saved"
24706 value. This function is registered as a callback with MySQL.
24707 @param[in] thd thread handle
24708 @param[in] save immediate result from check function */
24709 36 static void innodb_thread_concurrency_update(THD *thd, SYS_VAR *, void *,
24710 const void *save) {
24711 36 srv_thread_concurrency = *static_cast<const ulong *>(save);
24712
24713 36 ib::info(ER_IB_MSG_THREAD_CONCURRENCY_CHANGED, srv_thread_concurrency);
24714
24715 36 log_files_thread_concurrency_updated(*log_sys);
24716
24717
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 33 times.
36 if (!log_sys->concurrency_margin_is_safe.load()) {
24718 3 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
24719 "Current innodb_thread_concurrency"
24720 " is too big for safety of redo log files."
24721 " Consider decreasing it or increasing"
24722 " innodb_redo_log_capacity.");
24723 }
24724 36 }
24725
24726 /** Empty free list algorithm. This function is registered as a callback with
24727 MySQL.
24728 @param[in] thd thread handle
24729 @param[in] var pointer to system variable
24730 @param[out] save immediate result for update function
24731 @param[in] value incoming string
24732 @return 0 for valid algorithm */
24733 13 static int innodb_srv_empty_free_list_algorithm_validate(
24734 THD *thd, SYS_VAR *var, void *save, struct st_mysql_value *value) {
24735 char buff[STRING_BUFFER_USUAL_SIZE];
24736 13 int len = sizeof(buff);
24737
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 const char *const algorithm_name = value->val_str(value, buff, &len);
24738
24739
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (!algorithm_name) return (1);
24740
24741 ulint algo;
24742 22 for (algo = 0;
24743
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 2 times.
22 algo < array_elements(innodb_empty_free_list_algorithm_names) - 1;
24744 algo++) {
24745
3/4
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 9 times.
20 if (!innobase_strcasecmp(algorithm_name,
24746 innodb_empty_free_list_algorithm_names[algo]))
24747 11 break;
24748 }
24749
24750
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11 times.
13 if (algo == array_elements(innodb_empty_free_list_algorithm_names) - 1)
24751 2 return (1);
24752
24753 11 const auto algorithm = static_cast<srv_empty_free_list_t>(algo);
24754
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
11 if (!innodb_empty_free_list_algorithm_allowed(algorithm)) {
24755
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 sql_print_warning(
24756 "InnoDB: innodb_empty_free_list_algorithm = 'backoff' "
24757 "requires at least 20MB buffer pool instances.\n");
24758 2 return (1);
24759 }
24760
24761 9 *reinterpret_cast<ulong *>(save) = static_cast<ulong>(algorithm);
24762 9 return (0);
24763 }
24764
24765 10 static int innodb_encryption_threads_validate(
24766 /*=================================*/
24767 THD *thd, /*!< in: thread handle */
24768 SYS_VAR *var, /*!< in: pointer to system
24769 variable */
24770 void *save, /*!< out: immediate result
24771 for update function */
24772 struct st_mysql_value *value) /*!< in: incoming string */
24773 {
24774 long long intbuf;
24775
24776
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 DBUG_TRACE;
24777
24778
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
10 if (value->val_int(value, &intbuf)) {
24779 /* The value is NULL. That is invalid. */
24780 return 1;
24781 }
24782
24783 10 bool is_val_fixed = false;
24784 10 long long requested_threads = intbuf;
24785
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if (intbuf < 0) {
24786 2 requested_threads = 0;
24787 2 is_val_fixed = true;
24788
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
8 } else if (intbuf > MAX_ENCRYPTION_THREADS) {
24789 2 requested_threads = MAX_ENCRYPTION_THREADS;
24790 2 is_val_fixed = true;
24791 }
24792
24793
3/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
10 if (throw_bounds_warning(thd, "innodb_encryption_threads", is_val_fixed,
24794 intbuf)) {
24795 2 return 1;
24796 }
24797
24798
4/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3 times.
8 if (srv_n_fil_crypt_threads_requested == 0 && requested_threads > 0) {
24799 // We are starting encryption threads, we must lock
24800 // the keyring plugins
24801
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 uint number_of_keyrings_locked = lock_keyrings(NULL);
24802
24803
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (number_of_keyrings_locked == 0) {
24804 my_printf_error(ER_WRONG_ARGUMENTS,
24805 "InnoDB: cannot enable encryption threads, "
24806 "keyring plugin is not available",
24807 MYF(0));
24808 return 1;
24809 }
24810
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (Encryption::is_keyring_alive() == false) {
24811 my_printf_error(
24812 ER_WRONG_ARGUMENTS,
24813 "InnoDB: keyring plugin is installed but it seems it was not "
24814 "properly initialized. Cannot enable encryption threads.",
24815 MYF(0));
24816 unlock_keyrings(NULL);
24817 return 1;
24818 }
24819
4/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3 times.
8 } else if (requested_threads == 0 && srv_n_fil_crypt_threads_requested >
24820 0) { // We are disabling encryption
24821 // threads, unlock the keyrings
24822
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 unlock_keyrings(NULL);
24823 }
24824
24825 8 *reinterpret_cast<ulong *>(save) = static_cast<ulong>(requested_threads);
24826
24827 8 return 0;
24828 10 }
24829
24830 /******************************************************************
24831 Update the system variable innodb_encryption_threads */
24832 8 static void innodb_encryption_threads_update(
24833 /*=============================*/
24834 THD *thd, /*!< in: thread handle */
24835 SYS_VAR *var, /*!< in: pointer to
24836 system variable */
24837 void *var_ptr, /*!< out: where the
24838 formal string goes */
24839 const void *save) /*!< in: immediate result
24840 from check function */
24841 {
24842 8 mysql_mutex_unlock(&LOCK_global_system_variables);
24843 8 fil_crypt_set_thread_cnt(*static_cast<const uint *>(save));
24844 8 mysql_mutex_lock(&LOCK_global_system_variables);
24845 8 }
24846
24847 /******************************************************************
24848 Update the system variable innodb_encryption_rotate_key_age */
24849 3 static void innodb_encryption_rotate_key_age_update(
24850 /*====================================*/
24851 THD *thd, /*!< in: thread handle */
24852 SYS_VAR *var, /*!< in: pointer to
24853 system variable */
24854 void *var_ptr, /*!< out: where the
24855 formal string goes */
24856 const void *save) /*!< in: immediate result
24857 from check function */
24858 {
24859 3 fil_crypt_set_rotate_key_age(*static_cast<const uint *>(save));
24860 3 }
24861
24862 /******************************************************************
24863 Update the system variable innodb_encryption_rotation_iops */
24864 3 static void innodb_encryption_rotation_iops_update(
24865 /*===================================*/
24866 THD *thd, /*!< in: thread handle */
24867 SYS_VAR *var, /*!< in: pointer to
24868 system variable */
24869 void *var_ptr, /*!< out: where the
24870 formal string goes */
24871 const void *save) /*!< in: immediate result
24872 from check function */
24873 {
24874 3 fil_crypt_set_rotation_iops(*static_cast<const uint *>(save));
24875 3 }
24876
24877 /** Update the innodb_log_checksums parameter.
24878 @param[out] var_ptr current value
24879 @param[in] save immediate result from check function */
24880 7 static void innodb_log_checksums_update(THD *, SYS_VAR *, void *var_ptr,
24881 const void *save) {
24882 7 bool check = *static_cast<bool *>(var_ptr) = *static_cast<const bool *>(save);
24883
24884 /* Make sure we are the only log user */
24885 7 innodb_log_checksums_func_update(check);
24886 7 }
24887
24888 /** Enable or disable encryption of temporary tablespace
24889 @param[in] thd thread handle
24890 @param[in] var system variable
24891 @param[out] var_ptr current value
24892 @param[in] save immediate result from check function */
24893 15 static void innodb_temp_tablespace_encryption_update(THD *thd, SYS_VAR *var,
24894 void *var_ptr,
24895 const void *save) {
24896
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 14 times.
15 if (srv_read_only_mode) {
24897 1 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
24898 " Temporary tablespace cannot be"
24899 " encrypted in innodb_read_only mode");
24900 1 return;
24901 }
24902
24903 14 bool check = *static_cast<const bool *>(save);
24904
24905 14 dberr_t err = srv_temp_encryption_update(check);
24906
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
14 if (err != DB_SUCCESS) {
24907 2 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
24908 " Temporary tablespace couldn't be"
24909 " encrypted. Check if keyring plugin"
24910 " is loaded.");
24911 } else {
24912 12 *static_cast<bool *>(var_ptr) = *static_cast<const bool *>(save);
24913 }
24914 }
24915
24916 static SHOW_VAR innodb_status_variables_export[] = {
24917 {"Innodb", (char *)&show_innodb_vars, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
24918 {NullS, NullS, SHOW_LONG, SHOW_SCOPE_GLOBAL}};
24919
24920 static struct st_mysql_storage_engine innobase_storage_engine = {
24921 MYSQL_HANDLERTON_INTERFACE_VERSION};
24922
24923 #ifdef WITH_WSREP
24924 void wsrep_abort_slave_trx(wsrep_seqno_t bf_seqno, wsrep_seqno_t victim_seqno) {
24925 WSREP_ERROR(
24926 "Trx %lld tries to abort slave trx %lld. This could be "
24927 "caused by:\n\t"
24928 "1) unsupported configuration options combination, please check "
24929 "documentation.\n\t"
24930 "2) a bug in the code.\n\t"
24931 "3) a database corruption.\n Node consistency compromized, "
24932 "need to abort. Restart the node to resync with cluster.",
24933 (long long)bf_seqno, (long long)victim_seqno);
24934 abort();
24935 }
24936
24937 484 int wsrep_innobase_kill_one_trx(void *const bf_thd_ptr,
24938 const trx_t *const bf_trx, trx_t *victim_trx,
24939 bool signal) {
24940 // This is there in upstream codership 5.6 but causes
24941 // crashes, hence disabled
24942 // ut_ad(trx_mutex_own(victim_trx));
24943
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 484 times.
484 ut_ad(bf_thd_ptr);
24944
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 484 times.
484 ut_ad(victim_trx);
24945
24946
1/2
✓ Branch 0 taken 484 times.
✗ Branch 1 not taken.
484 DBUG_TRACE;
24947 484 THD *bf_thd = bf_thd_ptr ? (THD *)bf_thd_ptr : NULL;
24948 484 THD *thd = (THD *)victim_trx->mysql_thd;
24949
2/4
✓ Branch 0 taken 484 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 484 times.
✗ Branch 3 not taken.
484 int64_t bf_seqno = (bf_thd) ? wsrep_thd_trx_seqno(bf_thd) : 0;
24950
24951
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 484 times.
484 if (!thd) {
24952 DBUG_PRINT("wsrep", ("no thd for conflicting lock"));
24953 WSREP_WARN("no THD for victim trx: %llu", (long long)victim_trx->id);
24954 return 1;
24955 }
24956
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 484 times.
484 if (!bf_thd) {
24957 DBUG_PRINT("wsrep", ("no BF thd for conflicting lock"));
24958 WSREP_WARN("no THD for BF trx: %llu", (bf_trx) ? (long long)bf_trx->id : 0);
24959 return 1;
24960 }
24961
24962
57/120
✓ Branch 0 taken 484 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 482 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 2 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 2 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✓ Branch 23 taken 2 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✓ Branch 26 taken 2 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 2 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 2 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 2 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 2 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 2 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 2 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 2 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 2 times.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✓ Branch 45 taken 2 times.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✓ Branch 48 taken 2 times.
✗ Branch 49 not taken.
✓ Branch 50 taken 2 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 2 times.
✗ Branch 53 not taken.
✓ Branch 54 taken 2 times.
✗ Branch 55 not taken.
✓ Branch 56 taken 2 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 2 times.
✗ Branch 59 not taken.
✓ Branch 60 taken 2 times.
✗ Branch 61 not taken.
✓ Branch 62 taken 2 times.
✗ Branch 63 not taken.
✓ Branch 64 taken 2 times.
✗ Branch 65 not taken.
✓ Branch 66 taken 2 times.
✗ Branch 67 not taken.
✓ Branch 68 taken 2 times.
✗ Branch 69 not taken.
✓ Branch 70 taken 2 times.
✗ Branch 71 not taken.
✓ Branch 72 taken 2 times.
✗ Branch 73 not taken.
✓ Branch 74 taken 2 times.
✗ Branch 75 not taken.
✓ Branch 76 taken 2 times.
✗ Branch 77 not taken.
✓ Branch 78 taken 2 times.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✓ Branch 81 taken 2 times.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✓ Branch 84 taken 2 times.
✗ Branch 85 not taken.
✓ Branch 86 taken 2 times.
✗ Branch 87 not taken.
✓ Branch 88 taken 2 times.
✗ Branch 89 not taken.
✓ Branch 90 taken 2 times.
✗ Branch 91 not taken.
✓ Branch 92 taken 2 times.
✗ Branch 93 not taken.
✓ Branch 94 taken 2 times.
✗ Branch 95 not taken.
✓ Branch 96 taken 2 times.
✗ Branch 97 not taken.
✓ Branch 98 taken 2 times.
✗ Branch 99 not taken.
✓ Branch 100 taken 2 times.
✗ Branch 101 not taken.
✓ Branch 102 taken 2 times.
✗ Branch 103 not taken.
✓ Branch 104 taken 2 times.
✗ Branch 105 not taken.
✓ Branch 106 taken 2 times.
✗ Branch 107 not taken.
✓ Branch 108 taken 2 times.
✗ Branch 109 not taken.
✓ Branch 110 taken 2 times.
✗ Branch 111 not taken.
✓ Branch 112 taken 2 times.
✗ Branch 113 not taken.
✓ Branch 114 taken 2 times.
✗ Branch 115 not taken.
✗ Branch 116 not taken.
✓ Branch 117 taken 2 times.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
484 WSREP_LOG_CONFLICT(bf_thd, thd, true);
24963
1/2
✓ Branch 0 taken 484 times.
✗ Branch 1 not taken.
484 wsrep_thd_LOCK(thd);
24964
24965
1/28
✗ Branch 0 not taken.
✓ Branch 1 taken 484 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
484 WSREP_DEBUG(
24966 "BF thread %u (with write-set: %lld)"
24967 " aborting Victim thread %u with transaction (%llu)",
24968 wsrep_thd_thread_id(bf_thd), (long long)bf_seqno,
24969 wsrep_thd_thread_id(thd), (long long)victim_trx->id);
24970
24971
1/32
✗ Branch 0 not taken.
✓ Branch 1 taken 484 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
484 WSREP_DEBUG("Aborting query: %s",
24972 (thd && wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void");
24973
24974
5/8
✓ Branch 0 taken 484 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 483 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
484 DBUG_EXECUTE_IF("sync.wsrep_after_BF_victim_lock", {
24975 const char act[] =
24976 "now "
24977 "wait_for signal.wsrep_after_BF_victim_lock";
24978 assert(!debug_sync_set_action(bf_thd, STRING_WITH_LEN(act)));
24979 };);
24980
24981 /*
24982 * we mark with was_chosen_as_deadlock_victim transaction,
24983 * which is already marked as BF victim
24984 * lock_sys is held until this vicitm has aborted
24985 */
24986
2/2
✓ Branch 0 taken 472 times.
✓ Branch 1 taken 12 times.
484 if (victim_trx->state != TRX_STATE_NOT_STARTED) {
24987 472 victim_trx->lock.was_chosen_as_wsrep_victim = true;
24988 }
24989
24990
24991
2/4
✓ Branch 0 taken 484 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 484 times.
484 if (wsrep_thd_set_wsrep_aborter(bf_thd, thd)) {
24992 WSREP_DEBUG("innodb kill transaction skipped due to wsrep_aborter set");
24993 wsrep_thd_UNLOCK(thd);
24994 return 0;
24995 }
24996
24997
1/2
✓ Branch 0 taken 484 times.
✗ Branch 1 not taken.
484 wsrep_thd_UNLOCK(thd);
24998
24999
3/4
✓ Branch 0 taken 484 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 434 times.
✓ Branch 3 taken 50 times.
484 if (wsrep_thd_bf_abort(bf_thd, thd, signal)) {
25000
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 433 times.
434 if (victim_trx->lock.wait_lock) {
25001
1/26
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
1 WSREP_DEBUG(
25002 "victim: %lu has wait flag(suspended) and will be aborted by"
25003 " lock wait timeout thread",
25004 thd_get_thread_id(thd));
25005 /* Victim is already marked as interrupted but currently in suspended
25006 state (waiting for lock). The lock wait timeout thread releases the
25007 locks for transactions in interrupted state and wakes up the suspended
25008 thread. See lock_wait_check_and_cancel() */
25009 }
25010 } else {
25011
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 wsrep_thd_LOCK(thd);
25012 50 victim_trx->lock.was_chosen_as_deadlock_victim = false;
25013 50 victim_trx->lock.was_chosen_as_wsrep_victim = false;
25014
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 wsrep_thd_set_wsrep_aborter(nullptr, thd);
25015
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 wsrep_thd_UNLOCK(thd);
25016
25017
1/24
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
50 WSREP_DEBUG("wsrep_thd_bf_abort has failed, victim will survive");
25018 50 return 1;
25019 }
25020
25021 434 return 0;
25022 484 }
25023
25024 174 static int wsrep_abort_transaction_func(handlerton *hton, THD *bf_thd,
25025 THD *victim_thd, bool signal) {
25026
1/2
✓ Branch 0 taken 174 times.
✗ Branch 1 not taken.
174 DBUG_ENTER("wsrep_innobase_abort_thd");
25027
25028 /* Starting MySQL-8.0, same thd will be used to perform dictionary
25029 (or dd) object changes. These objects changes are done using a separate
25030 transaction that is created on the fly. Given the main innodb code
25031 is tuned to look at only 1 transaction object, the main transaction
25032 object needs to be backed up so that this temporary dd transaction object
25033 can be feeded for the said tenure. Once the dd update scope is complete
25034 main transaction object is restored.
25035 All this happens as part of attachable transaction that is member of thd.
25036 In the case below, PXC needs to look at victim transaction but this
25037 transaction could be dd transaction as explained above so PXC should
25038 carefully look for the needed victim transaction. This is needed
25039 as transaction is being accessed outside the main thd context.
25040 BF thd is trying to alter transaction state.
25041
25042 Below call should be mutex protected to avoid allowing victim
25043 thd executing routine to restore main transaction while bf_thd
25044 is in process to findout victim transaction */
25045
1/2
✓ Branch 0 taken 174 times.
✗ Branch 1 not taken.
174 mysql_mutex_lock(&victim_thd->LOCK_wsrep_thd_attachable_trx);
25046 /* This mutex lock is not needed but keeping it for now as safety check. */
25047
1/2
✓ Branch 0 taken 174 times.
✗ Branch 1 not taken.
174 mysql_mutex_lock(&victim_thd->LOCK_thd_data);
25048
1/2
✓ Branch 0 taken 174 times.
✗ Branch 1 not taken.
174 trx_t *victim_trx = wsrep_thd_to_trx(victim_thd);
25049
1/2
✓ Branch 0 taken 174 times.
✗ Branch 1 not taken.
174 mysql_mutex_unlock(&victim_thd->LOCK_thd_data);
25050
1/2
✓ Branch 0 taken 174 times.
✗ Branch 1 not taken.
174 mysql_mutex_unlock(&victim_thd->LOCK_wsrep_thd_attachable_trx);
25051
25052 /* mutex lock is not needed here as execution if being done by bf_thd. */
25053
2/4
✓ Branch 0 taken 174 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 174 times.
✗ Branch 3 not taken.
174 trx_t *bf_trx = (bf_thd) ? thd_to_trx(bf_thd) : NULL;
25054
1/28
✗ Branch 0 not taken.
✓ Branch 1 taken 174 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
174 WSREP_DEBUG("Abort Transaction BF query: %s Victim query: %s",
25055 wsrep_thd_query(bf_thd), wsrep_thd_query(victim_thd));
25056
25057
2/2
✓ Branch 0 taken 116 times.
✓ Branch 1 taken 58 times.
174 if (victim_trx) {
25058
4/8
✓ Branch 0 taken 116 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 116 times.
✓ Branch 4 taken 116 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 116 times.
✗ Branch 7 not taken.
116 trx_mutex_enter(victim_trx);
25059
1/2
✓ Branch 0 taken 116 times.
✗ Branch 1 not taken.
116 int rcode = wsrep_innobase_kill_one_trx(bf_thd, bf_trx, victim_trx, signal);
25060
4/8
✓ Branch 0 taken 116 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 116 times.
✓ Branch 4 taken 116 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 116 times.
✗ Branch 7 not taken.
116 trx_mutex_exit(victim_trx);
25061
1/2
✓ Branch 0 taken 116 times.
✗ Branch 1 not taken.
116 wsrep_srv_conc_cancel_wait(victim_trx);
25062
25063
1/2
✓ Branch 0 taken 116 times.
✗ Branch 1 not taken.
116 DBUG_RETURN(rcode);
25064 } else {
25065 /* Normally a background thread that is selected as victim doesn't have
25066 an active transaction associated with it. */
25067
1/24
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
58 WSREP_DEBUG("Victim Thread does not have transaction associated with it");
25068
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 wsrep_thd_bf_abort(bf_thd, victim_thd, signal);
25069 }
25070
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 DBUG_RETURN(-1);
25071 }
25072
25073 15627 static int innobase_wsrep_set_checkpoint(handlerton *hton, const XID *xid) {
25074
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15627 times.
15627 assert(hton == innodb_hton_ptr);
25075
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15627 times.
15627 if (srv_read_only_mode) return 0;
25076
1/2
✓ Branch 0 taken 15627 times.
✗ Branch 1 not taken.
15627 if (wsrep_is_wsrep_xid(xid)) {
25077
1/2
✓ Branch 0 taken 15627 times.
✗ Branch 1 not taken.
15627 mtr_t mtr;
25078
1/2
✓ Branch 0 taken 15627 times.
✗ Branch 1 not taken.
15627 mtr_start(&mtr);
25079
1/2
✓ Branch 0 taken 15627 times.
✗ Branch 1 not taken.
15627 trx_sysf_t *sys_header = trx_sysf_get(&mtr);
25080
1/2
✓ Branch 0 taken 15627 times.
✗ Branch 1 not taken.
15627 trx_sys_update_wsrep_checkpoint(xid, sys_header, &mtr);
25081
1/2
✓ Branch 0 taken 15627 times.
✗ Branch 1 not taken.
15627 mtr_commit(&mtr);
25082
1/2
✓ Branch 0 taken 15627 times.
✗ Branch 1 not taken.
15627 innobase_flush_logs(hton, false);
25083 15627 return 0;
25084 15627 } else {
25085 return 1;
25086 }
25087 }
25088
25089 1442 static int innobase_wsrep_get_checkpoint(handlerton *hton, XID *xid) {
25090
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1442 times.
1442 assert(hton == innodb_hton_ptr);
25091 1442 trx_sys_read_wsrep_checkpoint(xid);
25092 1442 return 0;
25093 }
25094 #endif /* WITH_WSREP */
25095
25096 /* plugin options */
25097
25098 static MYSQL_SYSVAR_ENUM(
25099 checksum_algorithm, srv_checksum_algorithm, PLUGIN_VAR_RQCMDARG,
25100 "The algorithm InnoDB uses for page checksumming. Possible values are"
25101 " CRC32 (hardware accelerated if the CPU supports it)"
25102 " write crc32, allow any of the other checksums to match when reading;"
25103 " STRICT_CRC32"
25104 " write crc32, do not allow other algorithms to match when reading;"
25105 " INNODB"
25106 " write a software calculated checksum, allow any other checksums"
25107 " to match when reading;"
25108 " STRICT_INNODB"
25109 " write a software calculated checksum, do not allow other algorithms"
25110 " to match when reading;"
25111 " NONE"
25112 " write a constant magic number, do not do any checksum verification"
25113 " when reading;"
25114 " STRICT_NONE"
25115 " write a constant magic number, do not allow values other than that"
25116 " magic number when reading;"
25117 " Files updated when this option is set to crc32 or strict_crc32 will"
25118 " not be readable by MySQL versions older than 5.6.3",
25119 nullptr, nullptr, SRV_CHECKSUM_ALGORITHM_CRC32,
25120 &innodb_checksum_algorithm_typelib);
25121
25122 static MYSQL_SYSVAR_BOOL(
25123 log_checksums, srv_log_checksums, PLUGIN_VAR_RQCMDARG,
25124 "Whether to compute and require checksums for InnoDB redo log blocks",
25125 nullptr, innodb_log_checksums_update, true);
25126
25127 static MYSQL_SYSVAR_STR(data_home_dir, innobase_data_home_dir,
25128 PLUGIN_VAR_READONLY | PLUGIN_VAR_NOPERSIST,
25129 "The common part for InnoDB table spaces.", nullptr,
25130 nullptr, nullptr);
25131
25132 static MYSQL_SYSVAR_BOOL(
25133 stats_include_delete_marked, srv_stats_include_delete_marked,
25134 PLUGIN_VAR_OPCMDARG,
25135 "Include delete marked records when calculating persistent statistics",
25136 nullptr, nullptr, false);
25137
25138 static MYSQL_SYSVAR_ULONG(
25139 io_capacity, srv_io_capacity, PLUGIN_VAR_RQCMDARG,
25140 "Number of IOPs the server can do. Tunes the background IO rate", nullptr,
25141 innodb_io_capacity_update, 200, 100, ~0UL, 0);
25142
25143 static MYSQL_SYSVAR_ULONG(io_capacity_max, srv_max_io_capacity,
25144 PLUGIN_VAR_RQCMDARG,
25145 "Limit to which innodb_io_capacity can be inflated.",
25146 nullptr, innodb_io_capacity_max_update,
25147 SRV_MAX_IO_CAPACITY_DUMMY_DEFAULT, 100,
25148 SRV_MAX_IO_CAPACITY_LIMIT, 0);
25149
25150 #ifdef UNIV_DEBUG
25151 static MYSQL_SYSVAR_BOOL(background_drop_list_empty,
25152 innodb_background_drop_list_empty, PLUGIN_VAR_OPCMDARG,
25153 "Wait for the background drop list to become empty",
25154 nullptr, wait_background_drop_list_empty, false);
25155
25156 static MYSQL_SYSVAR_BOOL(purge_run_now, innodb_purge_run_now,
25157 PLUGIN_VAR_OPCMDARG, "Set purge state to RUN", nullptr,
25158 purge_run_now_set, false);
25159
25160 static MYSQL_SYSVAR_BOOL(purge_stop_now, innodb_purge_stop_now,
25161 PLUGIN_VAR_OPCMDARG, "Set purge state to STOP",
25162 nullptr, purge_stop_now_set, false);
25163
25164 static MYSQL_SYSVAR_BOOL(log_flush_now, innodb_log_flush_now,
25165 PLUGIN_VAR_OPCMDARG,
25166 "Force flush of redo up to current lsn", nullptr,
25167 log_flush_now_set, false);
25168
25169 static MYSQL_SYSVAR_BOOL(log_checkpoint_now, innodb_log_checkpoint_now,
25170 PLUGIN_VAR_OPCMDARG, "Force sharp checkpoint now",
25171 nullptr, checkpoint_now_set, false);
25172
25173 static MYSQL_SYSVAR_BOOL(log_checkpoint_fuzzy_now,
25174 innodb_log_checkpoint_fuzzy_now, PLUGIN_VAR_OPCMDARG,
25175 "Force fuzzy checkpoint now", nullptr,
25176 checkpoint_fuzzy_now_set, false);
25177
25178 static MYSQL_SYSVAR_BOOL(checkpoint_disabled, srv_checkpoint_disabled,
25179 PLUGIN_VAR_OPCMDARG, "Disable checkpoints", nullptr,
25180 checkpoint_disabled_update, false);
25181
25182 static MYSQL_SYSVAR_BOOL(buf_flush_list_now, innodb_buf_flush_list_now,
25183 PLUGIN_VAR_OPCMDARG, "Force dirty page flush now",
25184 nullptr, buf_flush_list_now_set, false);
25185
25186 static MYSQL_SYSVAR_UINT(
25187 merge_threshold_set_all_debug, innodb_merge_threshold_set_all_debug,
25188 PLUGIN_VAR_RQCMDARG,
25189 "Override current MERGE_THRESHOLD setting for all indexes at dictionary"
25190 " cache by the specified value dynamically, at the time.",
25191 nullptr, innodb_merge_threshold_set_all_debug_update,
25192 DICT_INDEX_MERGE_THRESHOLD_DEFAULT, 1, 50, 0);
25193
25194 extern ulong srv_fatal_semaphore_wait_threshold;
25195 static MYSQL_SYSVAR_ULONG(
25196 semaphore_wait_timeout_debug, srv_fatal_semaphore_wait_threshold,
25197 PLUGIN_VAR_RQCMDARG,
25198 "Number of seconds that a semaphore can be held. If semaphore wait crosses"
25199 "this value, server will crash",
25200 nullptr, nullptr, 600, 25, 600, 0);
25201 #endif /* UNIV_DEBUG */
25202
25203 static MYSQL_SYSVAR_ULONG(
25204 purge_batch_size, srv_purge_batch_size, PLUGIN_VAR_OPCMDARG,
25205 "Number of UNDO log pages to purge in one batch from the history list.",
25206 nullptr, nullptr, 300, /* Default setting */
25207 1, /* Minimum value */
25208 5000, 0); /* Maximum value */
25209
25210 static MYSQL_SYSVAR_ULONG(purge_threads, srv_n_purge_threads,
25211 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
25212 "Purge threads can be from 1 to 32. Default is 4.",
25213 nullptr, nullptr, 4, /* Default setting */
25214 1, /* Minimum value */
25215 MAX_PURGE_THREADS, 0); /* Maximum value */
25216
25217 static MYSQL_SYSVAR_ULONG(sync_array_size, srv_sync_array_size,
25218 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
25219 "Size of the mutex/lock wait array.", nullptr,
25220 nullptr, 1, /* Default setting */
25221 1, /* Minimum value */
25222 1024, 0); /* Maximum value */
25223
25224 static MYSQL_SYSVAR_ULONG(
25225 fast_shutdown, srv_fast_shutdown, PLUGIN_VAR_OPCMDARG,
25226 "Speeds up the shutdown process of the InnoDB storage engine. Possible"
25227 " values are 0, 1 (faster) or 2 (fastest - crash-like).",
25228 nullptr, nullptr, 1, 0, 2, 0);
25229
25230 static MYSQL_SYSVAR_BOOL(
25231 file_per_table, srv_file_per_table, PLUGIN_VAR_NOCMDARG,
25232 "Stores each InnoDB table to an .ibd file in the database dir.", nullptr,
25233 nullptr, true);
25234
25235 static MYSQL_SYSVAR_STR(ft_server_stopword_table,
25236 innobase_server_stopword_table,
25237 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_MEMALLOC,
25238 "The user supplied stopword table name.",
25239 innodb_stopword_table_validate, nullptr, nullptr);
25240
25241 extern uint srv_flush_log_at_timeout;
25242 static MYSQL_SYSVAR_UINT(flush_log_at_timeout, srv_flush_log_at_timeout,
25243 PLUGIN_VAR_OPCMDARG,
25244 "Write and flush logs every (n) second.", nullptr,
25245 nullptr, 1, 0, 2700, 0);
25246
25247 static MYSQL_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit,
25248 PLUGIN_VAR_OPCMDARG,
25249 "Set to 0 (write and flush once per second),"
25250 " 1 (write and flush at each commit),"
25251 " or 2 (write at commit, flush once per second).",
25252 nullptr, nullptr, 1, 0, 2, 0);
25253
25254 static MYSQL_SYSVAR_ENUM(flush_method, innodb_flush_method,
25255 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
25256 "With which method to flush data", nullptr, nullptr, 0,
25257 &innodb_flush_method_typelib);
25258
25259 static MYSQL_SYSVAR_BOOL(force_load_corrupted, srv_load_corrupted,
25260 PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY |
25261 PLUGIN_VAR_NOPERSIST,
25262 "Force InnoDB to load metadata of corrupted table.",
25263 nullptr, nullptr, false);
25264
25265 static MYSQL_SYSVAR_ULONG(show_locks_held, srv_show_locks_held,
25266 PLUGIN_VAR_RQCMDARG,
25267 "Number of locks held to print for each InnoDB "
25268 "transaction in SHOW INNODB STATUS.",
25269 NULL, NULL, 10, 0, 1000, 0);
25270
25271 static MYSQL_SYSVAR_STR(log_group_home_dir, srv_log_group_home_dir,
25272 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY |
25273 PLUGIN_VAR_NOPERSIST,
25274 "Path to InnoDB log files.", nullptr, nullptr, nullptr);
25275
25276 static MYSQL_SYSVAR_ULONG(
25277 page_cleaners, srv_n_page_cleaners,
25278 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
25279 "Page cleaner threads can be from 1 to 64. Default is 4.", nullptr, nullptr,
25280 4, 1, 64, 0);
25281
25282 static MYSQL_SYSVAR_DOUBLE(max_dirty_pages_pct, srv_max_buf_pool_modified_pct,
25283 PLUGIN_VAR_RQCMDARG,
25284 "Percentage of dirty pages allowed in bufferpool.",
25285 nullptr, innodb_max_dirty_pages_pct_update, 90.0, 0,
25286 99.999, 0);
25287
25288 static MYSQL_SYSVAR_DOUBLE(
25289 max_dirty_pages_pct_lwm, srv_max_dirty_pages_pct_lwm, PLUGIN_VAR_RQCMDARG,
25290 "Percentage of dirty pages at which flushing kicks in.", nullptr,
25291 innodb_max_dirty_pages_pct_lwm_update, 10, 0, 99.999, 0);
25292
25293 static MYSQL_SYSVAR_ULONG(
25294 adaptive_flushing_lwm, srv_adaptive_flushing_lwm, PLUGIN_VAR_RQCMDARG,
25295 "Percentage of log capacity below which no adaptive flushing happens.",
25296 nullptr, nullptr, 10, 0, 70, 0);
25297
25298 static MYSQL_SYSVAR_BOOL(
25299 adaptive_flushing, srv_adaptive_flushing, PLUGIN_VAR_NOCMDARG,
25300 "Attempt flushing dirty pages to avoid IO bursts at checkpoints.", nullptr,
25301 nullptr, true);
25302
25303 static MYSQL_SYSVAR_BOOL(
25304 flush_sync, srv_flush_sync, PLUGIN_VAR_NOCMDARG,
25305 "Allow IO bursts at the checkpoints ignoring io_capacity setting.", nullptr,
25306 nullptr, true);
25307
25308 static MYSQL_SYSVAR_ULONG(
25309 flushing_avg_loops, srv_flushing_avg_loops, PLUGIN_VAR_RQCMDARG,
25310 "Number of iterations over which the background flushing is averaged.",
25311 nullptr, nullptr, 30, 1, 1000, 0);
25312
25313 static MYSQL_SYSVAR_ULONG(
25314 max_purge_lag, srv_max_purge_lag, PLUGIN_VAR_RQCMDARG,
25315 "Desired maximum length of the purge queue (0 = no limit)", nullptr,
25316 nullptr, 0, 0, ~0UL, 0);
25317
25318 static MYSQL_SYSVAR_ULONG(max_purge_lag_delay, srv_max_purge_lag_delay,
25319 PLUGIN_VAR_RQCMDARG,
25320 "Maximum delay of user threads in micro-seconds",
25321 nullptr, nullptr, 0L, /* Default seting */
25322 0L, /* Minimum value */
25323 10000000UL, 0); /* Maximum value */
25324
25325 static MYSQL_SYSVAR_BOOL(rollback_on_timeout, innobase_rollback_on_timeout,
25326 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
25327 "Roll back the complete transaction on lock wait "
25328 "timeout, for 4.x compatibility (disabled by default)",
25329 nullptr, nullptr, false);
25330
25331 static MYSQL_SYSVAR_BOOL(
25332 status_file, innobase_create_status_file,
25333 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOSYSVAR,
25334 "Enable SHOW ENGINE INNODB STATUS output in the innodb_status.<pid> file",
25335 nullptr, nullptr, false);
25336
25337 static MYSQL_SYSVAR_BOOL(
25338 stats_on_metadata, innobase_stats_on_metadata, PLUGIN_VAR_OPCMDARG,
25339 "Enable statistics gathering for metadata commands such as"
25340 " SHOW TABLE STATUS for tables that use transient statistics (off by "
25341 "default)",
25342 nullptr, nullptr, false);
25343
25344 static MYSQL_SYSVAR_ULONGLONG(
25345 stats_transient_sample_pages, srv_stats_transient_sample_pages,
25346 PLUGIN_VAR_RQCMDARG,
25347 "The number of leaf index pages to sample when calculating transient"
25348 " statistics (if persistent statistics are not used, default 8)",
25349 nullptr, nullptr, 8, 1, ~0ULL, 0);
25350
25351 static MYSQL_SYSVAR_BOOL(
25352 stats_persistent, srv_stats_persistent, PLUGIN_VAR_OPCMDARG,
25353 "InnoDB persistent statistics enabled for all tables unless overridden"
25354 " at table level",
25355 nullptr, nullptr, true);
25356
25357 static MYSQL_SYSVAR_BOOL(
25358 stats_auto_recalc, srv_stats_auto_recalc, PLUGIN_VAR_OPCMDARG,
25359 "InnoDB automatic recalculation of persistent statistics enabled for all"
25360 " tables unless overridden at table level (automatic recalculation is only"
25361 " done when InnoDB decides that the table has changed too much and needs a"
25362 " new statistics)",
25363 nullptr, nullptr, true);
25364
25365 static MYSQL_SYSVAR_ULONGLONG(
25366 stats_persistent_sample_pages, srv_stats_persistent_sample_pages,
25367 PLUGIN_VAR_RQCMDARG,
25368 "The number of leaf index pages to sample when calculating persistent"
25369 " statistics (by ANALYZE, default 20)",
25370 nullptr, nullptr, 20, 1, ~0ULL, 0);
25371
25372 static MYSQL_SYSVAR_BOOL(
25373 adaptive_hash_index, btr_search_enabled, PLUGIN_VAR_OPCMDARG,
25374 "Enable InnoDB adaptive hash index (enabled by default). "
25375 " Disable with --skip-innodb-adaptive-hash-index.",
25376 nullptr, innodb_adaptive_hash_index_update, true);
25377
25378 /** Number of distinct partitions of AHI.
25379 Each partition is protected by its own latch and so we have parts number
25380 of latches protecting complete search system. */
25381 static MYSQL_SYSVAR_ULONG(
25382 adaptive_hash_index_parts, btr_ahi_parts,
25383 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
25384 "Number of InnoDB Adaptive Hash Index Partitions. (default = 8). ", nullptr,
25385 nullptr, 8, 1, 512, 0);
25386
25387 extern ulong srv_replication_delay;
25388 static MYSQL_SYSVAR_ULONG(
25389 replication_delay, srv_replication_delay, PLUGIN_VAR_RQCMDARG,
25390 "Replication thread delay (ms) on the slave server if"
25391 " innodb_thread_concurrency is reached (0 by default)",
25392 nullptr, nullptr, 0, 0, ~0UL, 0);
25393
25394 static MYSQL_SYSVAR_UINT(
25395 compression_level, page_zip_level, PLUGIN_VAR_RQCMDARG,
25396 "Compression level used for compressed row format. 0 is no compression"
25397 ", 1 is fastest, 9 is best compression and default is 6.",
25398 nullptr, nullptr, DEFAULT_COMPRESSION_LEVEL, 0, 9, 0);
25399
25400 static MYSQL_SYSVAR_BOOL(
25401 log_compressed_pages, page_zip_log_pages, PLUGIN_VAR_OPCMDARG,
25402 "Enables/disables the logging of entire compressed page images."
25403 " InnoDB logs the compressed pages to prevent corruption if"
25404 " the zlib compression algorithm changes."
25405 " When turned OFF, InnoDB will assume that the zlib"
25406 " compression algorithm doesn't change.",
25407 nullptr, nullptr, true);
25408
25409 static MYSQL_SYSVAR_ULONG(autoextend_increment,
25410 sys_tablespace_auto_extend_increment,
25411 PLUGIN_VAR_RQCMDARG,
25412 "Data file autoextend increment in megabytes",
25413 nullptr, nullptr, 64L, 1L, 1000L, 0);
25414
25415 static MYSQL_SYSVAR_BOOL(
25416 dedicated_server, srv_dedicated_server,
25417 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_NOPERSIST | PLUGIN_VAR_READONLY,
25418 "Automatically scale innodb_buffer_pool_size and innodb_redo_log_capacity "
25419 "based on system memory. Also set innodb_flush_method=O_DIRECT_NO_FSYNC, "
25420 "if supported",
25421 nullptr, nullptr, false);
25422
25423 static MYSQL_SYSVAR_DOUBLE(
25424 segment_reserve_factor, fseg_reserve_pct, PLUGIN_VAR_OPCMDARG,
25425 "The segment_reserve_factor is the ratio x/y expressed in percentage,"
25426 " where x is the number of free pages in the segment, and y is the total"
25427 " number of pages in the segment. The number of used pages in the segment"
25428 " is given by (y-x). The number of free pages in the segment (x) will be"
25429 " maintained such that the actual segment_reserve_factor will be >= the"
25430 " requested segment_reserve_factor, which is contained in this variable.",
25431 nullptr, nullptr, FSEG_RESERVE_PCT_DFLT, FSEG_RESERVE_PCT_MIN,
25432 FSEG_RESERVE_PCT_MAX, 0);
25433
25434 /* If the default value of innodb_buffer_pool_size is increased to be more than
25435 BUF_POOL_SIZE_THRESHOLD (srv/srv0start.cc), then srv_buf_pool_instances_default
25436 can be removed and 8 used instead. The problem with the current setup is that
25437 with 128MiB default buffer pool size and 8 instances by default we would emit
25438 a warning when no options are specified. */
25439 static MYSQL_SYSVAR_LONGLONG(buffer_pool_size, srv_buf_pool_curr_size,
25440 PLUGIN_VAR_RQCMDARG |
25441 PLUGIN_VAR_PERSIST_AS_READ_ONLY,
25442 "The size of the memory buffer InnoDB uses to "
25443 "cache data and indexes of its tables.",
25444 nullptr, innodb_buffer_pool_size_update,
25445 static_cast<longlong>(srv_buf_pool_def_size),
25446 static_cast<longlong>(srv_buf_pool_min_size),
25447 longlong{srv_buf_pool_max_size}, 1024 * 1024L);
25448
25449 static MYSQL_SYSVAR_ULONGLONG(
25450 buffer_pool_chunk_size, srv_buf_pool_chunk_unit,
25451 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
25452 "Size of a single memory chunk within each buffer pool instance"
25453 " for resizing buffer pool. Online buffer pool resizing happens"
25454 " at this granularity.",
25455 nullptr, nullptr, 128 * 1024 * 1024, ulonglong{srv_buf_pool_chunk_unit_min},
25456 ulonglong{srv_buf_pool_chunk_unit_max},
25457 ulonglong{srv_buf_pool_chunk_unit_blk_sz});
25458
25459 #if defined UNIV_DEBUG || defined UNIV_PERF_DEBUG
25460 static MYSQL_SYSVAR_ULONG(page_hash_locks, srv_n_page_hash_locks,
25461 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
25462 "Number of rw_locks protecting buffer pool "
25463 "page_hash. Rounded up to the next power of 2",
25464 nullptr, nullptr, 16, 1, MAX_PAGE_HASH_LOCKS, 0);
25465
25466 #ifdef UNIV_LINUX
25467
25468 static MYSQL_SYSVAR_ULONG(sched_priority_purge, srv_sched_priority_purge,
25469 PLUGIN_VAR_RQCMDARG,
25470 "Nice value for the purge thread scheduling", NULL,
25471 innodb_sched_priority_purge_update, 19, 0, 39, 0);
25472
25473 static MYSQL_SYSVAR_ULONG(sched_priority_io, srv_sched_priority_io,
25474 PLUGIN_VAR_RQCMDARG,
25475 "Nice value for the I/O handler thread scheduling",
25476 NULL, innodb_sched_priority_io_update, 19, 0, 39, 0);
25477
25478 static MYSQL_SYSVAR_ULONG(sched_priority_master, srv_sched_priority_master,
25479 PLUGIN_VAR_RQCMDARG,
25480 "Nice value for the master thread scheduling", NULL,
25481 innodb_sched_priority_master_update, 19, 0, 39, 0);
25482
25483 static MYSQL_SYSVAR_BOOL(
25484 priority_purge, srv_purge_thread_priority, PLUGIN_VAR_OPCMDARG,
25485 "Make purge coordinator and worker threads acquire shared resources with "
25486 "priority",
25487 NULL, NULL, false);
25488
25489 static MYSQL_SYSVAR_BOOL(
25490 priority_master, srv_master_thread_priority, PLUGIN_VAR_OPCMDARG,
25491 "Make buffer pool cleaner thread acquire shared resources with priority",
25492 NULL, NULL, false);
25493
25494 #endif /* UNIV_LINUX */
25495
25496 // TODO: the option is here, but currently a no-op
25497 static MYSQL_SYSVAR_ULONG(
25498 cleaner_max_lru_time, srv_cleaner_max_lru_time, PLUGIN_VAR_RQCMDARG,
25499 "The maximum time limit for a single LRU tail flush iteration by the page "
25500 "cleaner thread in miliseconds",
25501 NULL, NULL, 1000, 0, ~0UL, 0);
25502
25503 // TODO: the option is here, but currently a no-op
25504 static MYSQL_SYSVAR_ULONG(cleaner_max_flush_time, srv_cleaner_max_flush_time,
25505 PLUGIN_VAR_RQCMDARG,
25506 "The maximum time limit for a single flush list "
25507 "flush iteration by the page "
25508 "cleaner thread in miliseconds",
25509 NULL, NULL, 1000, 0, ~0UL, 0);
25510 #endif /* defined UNIV_DEBUG || defined UNIV_PERF_DEBUG */
25511
25512 static MYSQL_SYSVAR_BOOL(
25513 validate_tablespace_paths, srv_validate_tablespace_paths,
25514 PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
25515 "Enable validation of tablespace paths against the DD. (enabled by "
25516 "default)."
25517 " Disable with --skip-innodb-validate-tablespace-paths.",
25518 nullptr, nullptr, true);
25519
25520 static MYSQL_SYSVAR_BOOL(use_fdatasync, srv_use_fdatasync, PLUGIN_VAR_NOCMDARG,
25521 "Use fdatasync() instead of the default fsync().",
25522 nullptr, nullptr, false);
25523
25524 // clang-format off
25525 static MYSQL_SYSVAR_ENUM(
25526 doublewrite, dblwr::g_mode, PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOPERSIST,
25527 "Enable InnoDB doublewrite buffer (enabled by default)."
25528 " Disable with --skip-innodb-doublewrite.",
25529 nullptr, doublewrite_update, dblwr::Mode::ON, &innodb_doublewrite_typelib);
25530
25531 static MYSQL_SYSVAR_BOOL(
25532 extend_and_initialize, tbsp_extend_and_initialize, PLUGIN_VAR_NOCMDARG,
25533 "Initialize the allocated space by writing zeros (enabled by default).",
25534 nullptr, innodb_extend_and_initialize_update, true);
25535
25536 static MYSQL_SYSVAR_STR(
25537 doublewrite_dir, innobase_doublewrite_dir, PLUGIN_VAR_READONLY,
25538 "Use a separate directory for the doublewrite buffer files, ", nullptr, nullptr,
25539 nullptr);
25540
25541 static MYSQL_SYSVAR_ULONG(
25542 doublewrite_pages, dblwr::n_pages,
25543 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
25544 "Number of double write pages per thread" , nullptr, nullptr, 0, 0, 512, 0);
25545
25546 static MYSQL_SYSVAR_ULONG(
25547 doublewrite_files, dblwr::n_files,
25548 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
25549 "Number of double write files", nullptr, nullptr, 0, 0, 256, 0);
25550
25551 static MYSQL_SYSVAR_ULONG(
25552 doublewrite_batch_size, dblwr::batch_size,
25553 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
25554 "Number of double write pages to write in a batch", nullptr, nullptr,
25555 0, 0, 256, 0);
25556 // clang-format on
25557
25558 static MYSQL_SYSVAR_ENUM(
25559 cleaner_lsn_age_factor, srv_cleaner_lsn_age_factor, PLUGIN_VAR_OPCMDARG,
25560 "The formula for LSN age factor for page cleaner adaptive flushing. "
25561 "LEGACY: Original Oracle MySQL formula. "
25562 "HIGH_CHECKPOINT: (the default) Percona Server formula.",
25563 nullptr, nullptr, SRV_CLEANER_LSN_AGE_FACTOR_HIGH_CHECKPOINT,
25564 &innodb_cleaner_lsn_age_factor_typelib);
25565
25566 static MYSQL_SYSVAR_ENUM(
25567 empty_free_list_algorithm, srv_empty_free_list_algorithm,
25568 PLUGIN_VAR_OPCMDARG,
25569 "The algorithm to use for empty free list handling. Allowed values: "
25570 "LEGACY: (the default) Original Oracle MySQL handling with single page "
25571 "flushes; "
25572 "BACKOFF: Wait until cleaner produces a free page.",
25573 innodb_srv_empty_free_list_algorithm_validate, nullptr,
25574 SRV_EMPTY_FREE_LIST_LEGACY, &innodb_empty_free_list_algorithm_typelib);
25575
25576 static MYSQL_SYSVAR_ULONG(buffer_pool_instances, srv_buf_pool_instances,
25577 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
25578 "Number of buffer pool instances, set to higher "
25579 "value on high-end machines to increase scalability",
25580 nullptr, nullptr, srv_buf_pool_instances_default, 0,
25581 MAX_BUFFER_POOLS, 0);
25582
25583 static MYSQL_SYSVAR_STR(
25584 buffer_pool_filename, srv_buf_dump_filename,
25585 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
25586 "Filename to/from which to dump/load the InnoDB buffer pool",
25587 innodb_srv_buf_dump_filename_validate, nullptr,
25588 SRV_BUF_DUMP_FILENAME_DEFAULT);
25589
25590 static MYSQL_SYSVAR_BOOL(buffer_pool_dump_now, innodb_buffer_pool_dump_now,
25591 PLUGIN_VAR_RQCMDARG,
25592 "Trigger an immediate dump of the buffer pool into a "
25593 "file named @@innodb_buffer_pool_filename",
25594 nullptr, buffer_pool_dump_now, false);
25595
25596 static MYSQL_SYSVAR_BOOL(
25597 buffer_pool_dump_at_shutdown, srv_buffer_pool_dump_at_shutdown,
25598 PLUGIN_VAR_RQCMDARG,
25599 "Dump the buffer pool into a file named @@innodb_buffer_pool_filename",
25600 nullptr, nullptr, true);
25601
25602 static MYSQL_SYSVAR_BOOL(
25603 buffer_pool_in_core_file, srv_buffer_pool_in_core_file, PLUGIN_VAR_NOCMDARG,
25604 "This option has no effect if @@core_file is OFF. "
25605 "If @@core_file is ON, and this option is OFF, then the core dump file will"
25606 " be generated only if it is possible to exclude buffer pool from it. "
25607 "As soon as it will be determined that such exclusion is impossible a "
25608 "warning will be emitted and @@core_file will be set to OFF to prevent "
25609 "generating a core dump. "
25610 "If this option is enabled (which is the default), then core dumping "
25611 "logic will not be affected. ",
25612 nullptr, innodb_srv_buffer_pool_in_core_file_update, true);
25613
25614 static MYSQL_SYSVAR_ULONG(
25615 buffer_pool_dump_pct, srv_buf_pool_dump_pct, PLUGIN_VAR_RQCMDARG,
25616 "Dump only the hottest N% of each buffer pool, defaults to 25", nullptr,
25617 nullptr, 25, 1, 100, 0);
25618
25619 static MYSQL_SYSVAR_ULONG(
25620 idle_flush_pct, srv_idle_flush_pct, PLUGIN_VAR_RQCMDARG,
25621 "Up to what percentage of dirty pages to be flushed when server is found"
25622 " idle.",
25623 nullptr, nullptr, srv_idle_flush_pct_default, 0, 100, 0);
25624
25625 #ifdef UNIV_DEBUG
25626 static MYSQL_SYSVAR_STR(buffer_pool_evict, srv_buffer_pool_evict,
25627 PLUGIN_VAR_RQCMDARG, "Evict pages from the buffer pool",
25628 nullptr, innodb_buffer_pool_evict_update, "");
25629 #endif /* UNIV_DEBUG */
25630
25631 static MYSQL_SYSVAR_BOOL(buffer_pool_load_now, innodb_buffer_pool_load_now,
25632 PLUGIN_VAR_RQCMDARG,
25633 "Trigger an immediate load of the buffer pool from a "
25634 "file named @@innodb_buffer_pool_filename",
25635 nullptr, buffer_pool_load_now, false);
25636
25637 static MYSQL_SYSVAR_BOOL(buffer_pool_load_abort, innodb_buffer_pool_load_abort,
25638 PLUGIN_VAR_RQCMDARG,
25639 "Abort a currently running load of the buffer pool",
25640 nullptr, buffer_pool_load_abort, false);
25641
25642 /* there is no point in changing this during runtime, thus readonly */
25643 static MYSQL_SYSVAR_BOOL(
25644 buffer_pool_load_at_startup, srv_buffer_pool_load_at_startup,
25645 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOPERSIST,
25646 "Load the buffer pool from a file named @@innodb_buffer_pool_filename",
25647 nullptr, nullptr, true);
25648
25649 static MYSQL_SYSVAR_ULONG(lru_scan_depth, srv_LRU_scan_depth,
25650 PLUGIN_VAR_RQCMDARG,
25651 "How deep to scan LRU to keep it clean", nullptr,
25652 nullptr, 1024, 100, ~0UL, 0);
25653
25654 static MYSQL_SYSVAR_ULONG(flush_neighbors, srv_flush_neighbors,
25655 PLUGIN_VAR_OPCMDARG,
25656 "Set to 0 (don't flush neighbors from buffer pool),"
25657 " 1 (flush contiguous neighbors from buffer pool)"
25658 " or 2 (flush neighbors from buffer pool),"
25659 " when flushing a block",
25660 nullptr, nullptr, 0, 0, 2, 0);
25661
25662 static MYSQL_SYSVAR_ULONG(
25663 commit_concurrency, innobase_commit_concurrency, PLUGIN_VAR_RQCMDARG,
25664 "Helps in performance tuning in heavily concurrent environments.",
25665 innobase_commit_concurrency_validate, nullptr, 0, 0, 1000, 0);
25666
25667 static MYSQL_SYSVAR_ULONG(concurrency_tickets, srv_n_free_tickets_to_enter,
25668 PLUGIN_VAR_RQCMDARG,
25669 "Number of times a thread is allowed to enter InnoDB "
25670 "within the same SQL query after it has once got the "
25671 "ticket",
25672 nullptr, nullptr, 5000L, 1L, UINT_MAX, 0);
25673
25674 static MYSQL_SYSVAR_BOOL(
25675 deadlock_detect, innobase_deadlock_detect, PLUGIN_VAR_NOCMDARG,
25676 "Enable/disable InnoDB deadlock detector (default ON)."
25677 " if set to OFF, deadlock detection is skipped,"
25678 " and we rely on innodb_lock_wait_timeout in case of deadlock.",
25679 nullptr, innobase_deadlock_detect_update, true);
25680
25681 static MYSQL_SYSVAR_LONG(fill_factor, ddl::fill_factor, PLUGIN_VAR_RQCMDARG,
25682 "Percentage of B-tree page filled during bulk insert",
25683 nullptr, nullptr, 100, 10, 100, 0);
25684
25685 static MYSQL_SYSVAR_BOOL(
25686 ft_enable_diag_print, fts_enable_diag_print, PLUGIN_VAR_OPCMDARG,
25687 "Whether to enable additional FTS diagnostic printout ", nullptr, nullptr,
25688 false);
25689
25690 static MYSQL_SYSVAR_BOOL(disable_sort_file_cache, srv_disable_sort_file_cache,
25691 PLUGIN_VAR_OPCMDARG,
25692 "Whether to disable OS system file cache for sort I/O",
25693 nullptr, nullptr, false);
25694
25695 static MYSQL_SYSVAR_STR(ft_aux_table, fts_internal_tbl_name,
25696 PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_MEMALLOC,
25697 "FTS internal auxiliary table to be checked",
25698 innodb_internal_table_validate, nullptr, nullptr);
25699
25700 static MYSQL_SYSVAR_ULONG(ft_cache_size, fts_max_cache_size,
25701 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
25702 "InnoDB Fulltext search cache size in bytes", nullptr,
25703 nullptr, 8000000, 1600000, 80000000, 0);
25704
25705 static MYSQL_SYSVAR_ULONG(
25706 ft_total_cache_size, fts_max_total_cache_size,
25707 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
25708 "Total memory allocated for InnoDB Fulltext Search cache", nullptr, nullptr,
25709 640000000, 32000000, 1600000000, 0);
25710
25711 static MYSQL_SYSVAR_ULONG(
25712 ft_result_cache_limit, fts_result_cache_limit, PLUGIN_VAR_RQCMDARG,
25713 "InnoDB Fulltext search query result cache limit in bytes", nullptr,
25714 nullptr, 2000000000L, 1000000L, 4294967295UL, 0);
25715
25716 static MYSQL_SYSVAR_ULONG(
25717 ft_min_token_size, fts_min_token_size,
25718 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
25719 "InnoDB Fulltext search minimum token size in characters", nullptr, nullptr,
25720 3, 0, 16, 0);
25721
25722 static MYSQL_SYSVAR_ULONG(
25723 ft_max_token_size, fts_max_token_size,
25724 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
25725 "InnoDB Fulltext search maximum token size in characters", nullptr, nullptr,
25726 FTS_MAX_WORD_LEN_IN_CHAR, 10, FTS_MAX_WORD_LEN_IN_CHAR, 0);
25727
25728 static MYSQL_SYSVAR_ULONG(ft_num_word_optimize, fts_num_word_optimize,
25729 PLUGIN_VAR_OPCMDARG,
25730 "InnoDB Fulltext search number of words to optimize "
25731 "for each optimize table call ",
25732 nullptr, nullptr, 2000, 1000, 10000, 0);
25733
25734 static MYSQL_SYSVAR_ULONG(ft_sort_pll_degree, ddl::fts_parser_threads,
25735 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
25736 "InnoDB Fulltext search parallel sort degree, will "
25737 "round up to nearest power of 2 number",
25738 nullptr, nullptr, 2, 1, 16, 0);
25739
25740 static MYSQL_SYSVAR_ULONG(sort_buffer_size, srv_sort_buf_size,
25741 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
25742 "Memory buffer size for index creation", nullptr,
25743 nullptr, 1048576, 65536, 64 << 20, 0);
25744
25745 static MYSQL_SYSVAR_ULONGLONG(
25746 online_alter_log_max_size, srv_online_max_size, PLUGIN_VAR_RQCMDARG,
25747 "Maximum modification log file size for online index creation", nullptr,
25748 nullptr, 128 << 20, 65536, ~0ULL, 0);
25749
25750 static MYSQL_SYSVAR_BOOL(optimize_fulltext_only, innodb_optimize_fulltext_only,
25751 PLUGIN_VAR_NOCMDARG,
25752 "Only optimize the Fulltext index of the table",
25753 nullptr, nullptr, false);
25754
25755 static MYSQL_SYSVAR_ULONG(read_io_threads, srv_n_read_io_threads,
25756 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
25757 "Number of background read I/O threads in InnoDB.",
25758 nullptr, nullptr, 4, 1, 64, 0);
25759
25760 static MYSQL_SYSVAR_ULONG(write_io_threads, srv_n_write_io_threads,
25761 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
25762 "Number of background write I/O threads in InnoDB.",
25763 nullptr, nullptr, 4, 1, 64, 0);
25764
25765 static MYSQL_SYSVAR_ULONG(force_recovery, srv_force_recovery,
25766 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
25767 "Helps to save your data in case the disk image of "
25768 "the database becomes corrupt.",
25769 nullptr, nullptr, 0, 0, 6, 0);
25770
25771 #ifdef UNIV_DEBUG
25772 static MYSQL_SYSVAR_ULONG(force_recovery_crash, srv_force_recovery_crash,
25773 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
25774 "Kills the server during crash recovery.", nullptr,
25775 nullptr, 0, 0, 100, 0);
25776 #endif /* UNIV_DEBUG */
25777
25778 static MYSQL_SYSVAR_ULONG(page_size, srv_page_size,
25779 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY |
25780 PLUGIN_VAR_NOPERSIST,
25781 "Page size to use for all InnoDB tablespaces.",
25782 nullptr, nullptr, UNIV_PAGE_SIZE_DEF,
25783 UNIV_PAGE_SIZE_MIN, UNIV_PAGE_SIZE_MAX, 0);
25784
25785 static MYSQL_SYSVAR_ULONG(
25786 log_buffer_size, srv_log_buffer_size, PLUGIN_VAR_RQCMDARG,
25787 "The size of the buffer which InnoDB uses to write log to the log files"
25788 " on disk.",
25789 nullptr, innodb_log_buffer_size_update, INNODB_LOG_BUFFER_SIZE_DEFAULT,
25790 INNODB_LOG_BUFFER_SIZE_MIN, INNODB_LOG_BUFFER_SIZE_MAX, 1024);
25791
25792 static MYSQL_SYSVAR_ULONGLONG(
25793 log_file_size, srv_log_file_size, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
25794 "Size of each log file before upgrading to 8.0.30. Deprecated.", nullptr,
25795 nullptr, 48 * 1024 * 1024L, 4 * 1024 * 1024L, ULLONG_MAX, 1024 * 1024L);
25796
25797 static MYSQL_SYSVAR_ULONG(
25798 log_files_in_group, srv_log_n_files,
25799 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
25800 "Number of log files before upgrading to 8.0.30. Deprecated.", nullptr,
25801 nullptr, 2, 2, 100, 0);
25802
25803 static MYSQL_SYSVAR_ULONGLONG(
25804 redo_log_capacity, srv_redo_log_capacity,
25805 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_PERSIST_AS_READ_ONLY,
25806 "Limitation for total size of redo log files on disk (expressed in bytes).",
25807 nullptr, innodb_redo_log_capacity_update, 100 * 1024 * 1024,
25808 LOG_CAPACITY_MIN, LOG_CAPACITY_MAX, MB);
25809
25810 #ifdef UNIV_DEBUG_DEDICATED
25811 static MYSQL_SYSVAR_ULONG(
25812 debug_sys_mem_size, srv_debug_system_mem_size,
25813 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
25814 "System memory size. It's for debuging dedicated server.", NULL, NULL,
25815 48 * 1024 * 1024L, 4 * 1024 * 1024L, ULLONG_MAX, 1024 * 1024L);
25816 #endif /* UNIV_DEBUG_DEDICATED */
25817
25818 static MYSQL_SYSVAR_ULONG(log_write_ahead_size, srv_log_write_ahead_size,
25819 PLUGIN_VAR_RQCMDARG,
25820 "Log write ahead unit size to avoid read-on-write,"
25821 " it should match the OS cache block IO size.",
25822 nullptr, innodb_log_write_ahead_size_update,
25823 INNODB_LOG_WRITE_AHEAD_SIZE_DEFAULT,
25824 INNODB_LOG_WRITE_AHEAD_SIZE_MIN,
25825 INNODB_LOG_WRITE_AHEAD_SIZE_MAX,
25826 OS_FILE_LOG_BLOCK_SIZE);
25827
25828 static MYSQL_SYSVAR_BOOL(
25829 log_writer_threads, srv_log_writer_threads, PLUGIN_VAR_RQCMDARG,
25830 "Whether the log writer threads should be activated (ON), or write/flush "
25831 "of the redo log should be done by each thread individually (OFF).",
25832 nullptr, innodb_log_writer_threads_update, true);
25833
25834 static MYSQL_SYSVAR_UINT(
25835 log_spin_cpu_abs_lwm, srv_log_spin_cpu_abs_lwm, PLUGIN_VAR_RQCMDARG,
25836 "Minimum value of cpu time for which spin-delay is used."
25837 " Expressed in percentage of single cpu core.",
25838 nullptr, nullptr, INNODB_LOG_SPIN_CPU_ABS_LWM_DEFAULT, 0, UINT_MAX, 0);
25839
25840 static MYSQL_SYSVAR_UINT(
25841 log_spin_cpu_pct_hwm, srv_log_spin_cpu_pct_hwm, PLUGIN_VAR_RQCMDARG,
25842 "Maximum value of cpu time for which spin-delay is used."
25843 " Expressed in percentage of all cpu cores.",
25844 nullptr, nullptr, INNODB_LOG_SPIN_CPU_PCT_HWM_DEFAULT, 0, 100, 0);
25845
25846 static MYSQL_SYSVAR_ULONG(
25847 log_wait_for_flush_spin_hwm, srv_log_wait_for_flush_spin_hwm,
25848 PLUGIN_VAR_RQCMDARG,
25849 "Maximum value of average log flush time for which spin-delay is used."
25850 " When flushing takes longer, user threads no longer spin when waiting for"
25851 "flushed redo. Expressed in microseconds.",
25852 nullptr, nullptr, INNODB_LOG_WAIT_FOR_FLUSH_SPIN_HWM_DEFAULT, 0, ULONG_MAX,
25853 0);
25854
25855 #ifdef ENABLE_EXPERIMENT_SYSVARS
25856
25857 static MYSQL_SYSVAR_ULONG(
25858 log_write_events, srv_log_write_events,
25859 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
25860 "Number of events used for notifications about log write.", NULL, NULL,
25861 INNODB_LOG_EVENTS_DEFAULT, INNODB_LOG_EVENTS_MIN, INNODB_LOG_EVENTS_MAX, 0);
25862
25863 static MYSQL_SYSVAR_ULONG(
25864 log_flush_events, srv_log_flush_events,
25865 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
25866 "Number of events used for notifications about log flush.", NULL, NULL,
25867 INNODB_LOG_EVENTS_DEFAULT, INNODB_LOG_EVENTS_MIN, INNODB_LOG_EVENTS_MAX, 0);
25868
25869 static MYSQL_SYSVAR_ULONG(
25870 log_recent_written_size, srv_log_recent_written_size,
25871 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
25872 "Size of a small buffer, which allows concurrent writes to log buffer.",
25873 NULL, NULL, INNODB_LOG_RECENT_WRITTEN_SIZE_DEFAULT,
25874 INNODB_LOG_RECENT_WRITTEN_SIZE_MIN, INNODB_LOG_RECENT_WRITTEN_SIZE_MAX, 0);
25875
25876 static MYSQL_SYSVAR_ULONG(
25877 log_recent_closed_size, srv_log_recent_closed_size,
25878 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
25879 "Size of a small buffer, which allows to break requirement for total order"
25880 " of dirty pages, when they are added to flush lists.",
25881 NULL, NULL, INNODB_LOG_RECENT_CLOSED_SIZE_DEFAULT,
25882 INNODB_LOG_RECENT_CLOSED_SIZE_MIN, INNODB_LOG_RECENT_CLOSED_SIZE_MAX, 0);
25883
25884 static MYSQL_SYSVAR_ULONG(
25885 log_wait_for_write_spin_delay, srv_log_wait_for_write_spin_delay,
25886 PLUGIN_VAR_RQCMDARG,
25887 "Number of spin iterations, when spinning and waiting for log buffer"
25888 " written up to given LSN, before we fallback to loop with sleeps."
25889 " This is not used when user thread has to wait for log flushed to disk.",
25890 NULL, NULL, INNODB_LOG_WAIT_FOR_WRITE_SPIN_DELAY_DEFAULT, 0, ULONG_MAX, 0);
25891
25892 extern ulong srv_log_wait_for_write_timeout;
25893 static MYSQL_SYSVAR_ULONG(
25894 log_wait_for_write_timeout, srv_log_wait_for_write_timeout,
25895 PLUGIN_VAR_RQCMDARG,
25896 "Timeout used when waiting for redo write (microseconds).", NULL, NULL,
25897 INNODB_LOG_WAIT_FOR_WRITE_TIMEOUT_DEFAULT, 0, ULONG_MAX, 0);
25898
25899 static MYSQL_SYSVAR_ULONG(
25900 log_wait_for_flush_spin_delay, srv_log_wait_for_flush_spin_delay,
25901 PLUGIN_VAR_RQCMDARG,
25902 "Number of spin iterations, when spinning and waiting for log flushed.",
25903 NULL, NULL, INNODB_LOG_WAIT_FOR_FLUSH_SPIN_DELAY_DEFAULT, 0, ULONG_MAX, 0);
25904
25905 extern ulong srv_log_wait_for_flush_timeout;
25906 static MYSQL_SYSVAR_ULONG(
25907 log_wait_for_flush_timeout, srv_log_wait_for_flush_timeout,
25908 PLUGIN_VAR_RQCMDARG,
25909 "Timeout used when waiting for redo flush (microseconds).", NULL, NULL,
25910 INNODB_LOG_WAIT_FOR_FLUSH_TIMEOUT_DEFAULT, 0, ULONG_MAX, 0);
25911
25912 static MYSQL_SYSVAR_ULONG(
25913 log_write_max_size, srv_log_write_max_size, PLUGIN_VAR_RQCMDARG,
25914 "Size available for next write, which satisfies log_writer thread"
25915 " when it follows links in recent written buffer.",
25916 NULL, NULL, INNODB_LOG_WRITE_MAX_SIZE_DEFAULT, 0, ULONG_MAX,
25917 OS_FILE_LOG_BLOCK_SIZE);
25918
25919 static MYSQL_SYSVAR_ULONG(
25920 log_writer_spin_delay, srv_log_writer_spin_delay, PLUGIN_VAR_RQCMDARG,
25921 "Number of spin iterations, for which log writer thread is waiting"
25922 " for new data to write without sleeping.",
25923 NULL, NULL, INNODB_LOG_WRITER_SPIN_DELAY_DEFAULT, 0, ULONG_MAX, 0);
25924
25925 extern ulong srv_log_writer_timeout;
25926 static MYSQL_SYSVAR_ULONG(
25927 log_writer_timeout, srv_log_writer_timeout, PLUGIN_VAR_RQCMDARG,
25928 "Initial timeout used to wait on event in log writer thread (microseconds)",
25929 NULL, NULL, INNODB_LOG_WRITER_TIMEOUT_DEFAULT, 0, ULONG_MAX, 0);
25930
25931 extern ulong srv_log_checkpoint_every;
25932 static MYSQL_SYSVAR_ULONG(
25933 log_checkpoint_every, srv_log_checkpoint_every, PLUGIN_VAR_RQCMDARG,
25934 "Checkpoints are executed at least every that many milliseconds.", NULL,
25935 NULL, INNODB_LOG_CHECKPOINT_EVERY_DEFAULT, 0, ULONG_MAX, 0);
25936
25937 static MYSQL_SYSVAR_ULONG(
25938 log_flusher_spin_delay, srv_log_flusher_spin_delay, PLUGIN_VAR_RQCMDARG,
25939 "Number of spin iterations, for which log flusher thread is waiting"
25940 " for new data to flush, without sleeping.",
25941 NULL, NULL, INNODB_LOG_FLUSHER_SPIN_DELAY_DEFAULT, 0, ULONG_MAX, 0);
25942
25943 extern ulong srv_log_flusher_timeout;
25944 static MYSQL_SYSVAR_ULONG(log_flusher_timeout, srv_log_flusher_timeout,
25945 PLUGIN_VAR_RQCMDARG,
25946 "Initial timeout used to wait on event in log "
25947 "flusher thread (microseconds)",
25948 NULL, NULL, INNODB_LOG_FLUSHER_TIMEOUT_DEFAULT, 0,
25949 ULONG_MAX, 0);
25950
25951 static MYSQL_SYSVAR_ULONG(
25952 log_write_notifier_spin_delay, srv_log_write_notifier_spin_delay,
25953 PLUGIN_VAR_RQCMDARG,
25954 "Number of spin iterations, for which log write notifier thread is waiting"
25955 " for advanced write_lsn, without sleeping.",
25956 NULL, NULL, INNODB_LOG_WRITE_NOTIFIER_SPIN_DELAY_DEFAULT, 0, ULONG_MAX, 0);
25957
25958 extern ulong srv_log_write_notifier_timeout;
25959 static MYSQL_SYSVAR_ULONG(
25960 log_write_notifier_timeout, srv_log_write_notifier_timeout,
25961 PLUGIN_VAR_RQCMDARG,
25962 "Initial timeout used to wait on event in log write notifier thread"
25963 " (microseconds)",
25964 NULL, NULL, INNODB_LOG_WRITE_NOTIFIER_TIMEOUT_DEFAULT, 0, ULONG_MAX, 0);
25965
25966 static MYSQL_SYSVAR_ULONG(
25967 log_flush_notifier_spin_delay, srv_log_flush_notifier_spin_delay,
25968 PLUGIN_VAR_RQCMDARG,
25969 "Number of spin iterations, for which log flush notifier thread is waiting"
25970 " for advanced flushed_to_disk_lsn, without sleeping.",
25971 NULL, NULL, INNODB_LOG_FLUSH_NOTIFIER_SPIN_DELAY_DEFAULT, 0, ULONG_MAX, 0);
25972
25973 extern ulong srv_log_flush_notifier_timeout;
25974 static MYSQL_SYSVAR_ULONG(
25975 log_flush_notifier_timeout, srv_log_flush_notifier_timeout,
25976 PLUGIN_VAR_RQCMDARG,
25977 "Initial timeout used to wait on event in log flush notifier thread"
25978 " (microseconds)",
25979 NULL, NULL, INNODB_LOG_FLUSH_NOTIFIER_TIMEOUT_DEFAULT, 0, ULONG_MAX, 0);
25980
25981 #endif /* ENABLE_EXPERIMENT_SYSVARS */
25982
25983 static MYSQL_SYSVAR_UINT(
25984 old_blocks_pct, innobase_old_blocks_pct, PLUGIN_VAR_RQCMDARG,
25985 "Percentage of the buffer pool to reserve for 'old' blocks.", nullptr,
25986 innodb_old_blocks_pct_update, 100 * 3 / 8, 5, 95, 0);
25987
25988 extern uint buf_LRU_old_threshold;
25989 static MYSQL_SYSVAR_UINT(
25990 old_blocks_time, buf_LRU_old_threshold, PLUGIN_VAR_RQCMDARG,
25991 "Move blocks to the 'new' end of the buffer pool if the first access"
25992 " was at least this many milliseconds ago."
25993 " The timeout is disabled if 0.",
25994 nullptr, nullptr, 1000, 0, UINT_MAX32, 0);
25995
25996 static MYSQL_SYSVAR_LONG(
25997 open_files, innobase_open_files, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
25998 "How many files at the maximum InnoDB keeps open at the same time.",
25999 nullptr, nullptr, 0L, 0L, LONG_MAX, 0);
26000
26001 static MYSQL_SYSVAR_ULONG(
26002 sync_spin_loops, srv_n_spin_wait_rounds, PLUGIN_VAR_RQCMDARG,
26003 "Count of spin-loop rounds in InnoDB mutexes (30 by default)", nullptr,
26004 nullptr, 30L, 0L, ~0UL, 0);
26005
26006 static MYSQL_SYSVAR_ULONG(
26007 spin_wait_delay, srv_spin_wait_delay, PLUGIN_VAR_OPCMDARG,
26008 "Maximum delay between polling for a spin lock (6 by default)", nullptr,
26009 nullptr, 6L, 0L, 1000, 0);
26010
26011 static MYSQL_SYSVAR_ULONG(spin_wait_pause_multiplier,
26012 ut::spin_wait_pause_multiplier, PLUGIN_VAR_RQCMDARG,
26013 "Controls how many times in a row to use a PAUSE "
26014 "instruction to achieve one unit of delay in a spin "
26015 "lock (see @@innodb_spin_wait_delay), defaults to 50",
26016 nullptr, nullptr, 50, 0, 100, 0);
26017
26018 static MYSQL_SYSVAR_ULONGLONG(
26019 fsync_threshold, os_fsync_threshold, PLUGIN_VAR_RQCMDARG,
26020 "The value of this variable determines how often InnoDB calls fsync when "
26021 "creating a new file. Default is zero which would make InnoDB flush the "
26022 "entire file at once before closing it.",
26023 nullptr, nullptr, 0, 0, ~0ULL, UNIV_PAGE_SIZE);
26024
26025 static MYSQL_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency,
26026 PLUGIN_VAR_RQCMDARG,
26027 "Helps in performance tuning in heavily concurrent "
26028 "environments. Sets the maximum number of threads "
26029 "allowed inside InnoDB. Value 0 will disable the "
26030 "thread throttling.",
26031 nullptr, innodb_thread_concurrency_update, 0, 0, 1000,
26032 0);
26033
26034 static MYSQL_SYSVAR_ULONG(
26035 adaptive_max_sleep_delay, srv_adaptive_max_sleep_delay, PLUGIN_VAR_RQCMDARG,
26036 "The upper limit of the sleep delay in usec. Value of 0 disables it.",
26037 nullptr, nullptr, 150000, /* Default setting */
26038 0, /* Minimum value */
26039 1000000, 0); /* Maximum value */
26040
26041 static MYSQL_SYSVAR_ULONG(
26042 thread_sleep_delay, srv_thread_sleep_delay, PLUGIN_VAR_RQCMDARG,
26043 "Time of innodb thread sleeping before joining InnoDB queue (usec)."
26044 " Value 0 disable a sleep",
26045 nullptr, nullptr, 10000L, 0L, 1000000L, 0);
26046
26047 static MYSQL_SYSVAR_STR(data_file_path, innobase_data_file_path,
26048 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY |
26049 PLUGIN_VAR_NOPERSIST,
26050 "Path to individual files and their sizes.", nullptr,
26051 nullptr, (char *)"ibdata1:12M:autoextend");
26052
26053 static MYSQL_SYSVAR_STR(temp_data_file_path, innobase_temp_data_file_path,
26054 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY |
26055 PLUGIN_VAR_NOPERSIST,
26056 "Path to files and their sizes making temp-tablespace.",
26057 nullptr, nullptr, (char *)"ibtmp1:12M:autoextend");
26058
26059 static MYSQL_SYSVAR_BOOL(
26060 temp_tablespace_encrypt, srv_tmp_tablespace_encrypt, PLUGIN_VAR_OPCMDARG,
26061 "Enable or disable encryption of temporary tablespace.", nullptr,
26062 innodb_temp_tablespace_encryption_update, false);
26063
26064 static MYSQL_SYSVAR_ENUM(
26065 sys_tablespace_encrypt, srv_sys_tablespace_encrypt,
26066 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOPERSIST,
26067 "Enable this option at bootstrap to encrypt system tablespace."
26068 "Set it to RE_ENCRYPTING_TO_KEYRING to allow re-encryption to KEYRING.",
26069 innodb_sys_tablespace_encyption_validate, nullptr,
26070 SYS_TABLESPACE_ENCRYPT_OFF, &sys_tablespace_encrypt_typelib);
26071
26072 static MYSQL_SYSVAR_STR(
26073 undo_directory, srv_undo_dir,
26074 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOPERSIST,
26075 "Directory where undo tablespace files live, this path can be absolute.",
26076 nullptr, nullptr, nullptr);
26077
26078 static MYSQL_SYSVAR_STR(
26079 temp_tablespaces_dir, ibt::srv_temp_dir,
26080 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOPERSIST,
26081 "Directory where temp tablespace files live, this path can be absolute.",
26082 nullptr, nullptr, nullptr);
26083
26084 static MYSQL_SYSVAR_ULONG(undo_tablespaces, srv_undo_tablespaces,
26085 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_NOPERSIST,
26086 "Number of undo tablespaces to use. (deprecated)",
26087 nullptr, innodb_undo_tablespaces_update,
26088 FSP_IMPLICIT_UNDO_TABLESPACES, /* Default seting */
26089 FSP_MIN_UNDO_TABLESPACES, /* Minimum value */
26090 FSP_MAX_UNDO_TABLESPACES, 0); /* Maximum value */
26091
26092 static MYSQL_SYSVAR_ULONGLONG(
26093 max_undo_log_size, srv_max_undo_tablespace_size, PLUGIN_VAR_OPCMDARG,
26094 "Maximum size of an UNDO tablespace in MB (If an UNDO tablespace grows"
26095 " beyond this size it will be truncated in due course). ",
26096 nullptr, nullptr, 1024 * 1024 * 1024L, 10 * 1024 * 1024L, ~0ULL, 0);
26097
26098 static MYSQL_SYSVAR_ULONG(
26099 purge_rseg_truncate_frequency, srv_purge_rseg_truncate_frequency,
26100 PLUGIN_VAR_OPCMDARG,
26101 "Dictates rate at which UNDO records are purged. Value N means"
26102 " purge rollback segment(s) on every Nth iteration of purge invocation",
26103 nullptr, nullptr, 128, 1, 128, 0);
26104
26105 static MYSQL_SYSVAR_BOOL(undo_log_truncate, srv_undo_log_truncate,
26106 PLUGIN_VAR_OPCMDARG,
26107 "Enable or Disable Truncate of UNDO tablespace.",
26108 nullptr, nullptr, true);
26109
26110 /* This is the number of rollback segments per undo tablespace.
26111 This applies to the temporary tablespace, the system tablespace,
26112 and all undo tablespaces. */
26113 static MYSQL_SYSVAR_ULONG(
26114 rollback_segments, srv_rollback_segments, PLUGIN_VAR_OPCMDARG,
26115 "Number of rollback segments per tablespace. This applies to the system"
26116 " tablespace, the temporary tablespace & any undo tablespace.",
26117 nullptr, innodb_rollback_segments_update,
26118 FSP_MAX_ROLLBACK_SEGMENTS, /* Default setting */
26119 1, /* Minimum value */
26120 FSP_MAX_ROLLBACK_SEGMENTS, 0); /* Maximum value */
26121
26122 static MYSQL_SYSVAR_BOOL(undo_log_encrypt, srv_undo_log_encrypt,
26123 PLUGIN_VAR_OPCMDARG,
26124 "Enable or disable Encrypt of UNDO tablespace.",
26125 validate_innodb_undo_log_encrypt, nullptr, false);
26126
26127 static MYSQL_SYSVAR_LONG(
26128 autoinc_lock_mode, innobase_autoinc_lock_mode,
26129 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
26130 "The AUTOINC lock modes supported by InnoDB:"
26131 " 0 => Old style AUTOINC locking (for backward compatibility);"
26132 " 1 => New style AUTOINC locking;"
26133 " 2 => No AUTOINC locking (unsafe for SBR)",
26134 nullptr, nullptr, AUTOINC_NO_LOCKING, /* Default setting */
26135 AUTOINC_OLD_STYLE_LOCKING, /* Minimum value */
26136 AUTOINC_NO_LOCKING, 0); /* Maximum value */
26137
26138 static MYSQL_SYSVAR_STR(version, innodb_version_str,
26139 PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_READONLY |
26140 PLUGIN_VAR_NOPERSIST,
26141 "InnoDB version", nullptr, nullptr, INNODB_VERSION_STR);
26142
26143 static MYSQL_SYSVAR_BOOL(use_native_aio, srv_use_native_aio,
26144 PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
26145 "Use native AIO if supported on this platform.",
26146 nullptr, nullptr, true);
26147
26148 #ifdef HAVE_LIBNUMA
26149 static MYSQL_SYSVAR_BOOL(
26150 numa_interleave, srv_numa_interleave,
26151 PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
26152 "Use NUMA interleave memory policy to allocate InnoDB buffer pool.",
26153 nullptr, nullptr, false);
26154 #endif /* HAVE_LIBNUMA */
26155
26156 static MYSQL_SYSVAR_BOOL(
26157 api_enable_binlog, ib_binlog_enabled,
26158 PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
26159 "Enable binlog for applications direct access InnoDB through InnoDB APIs",
26160 nullptr, nullptr, false);
26161
26162 static MYSQL_SYSVAR_BOOL(
26163 api_enable_mdl, ib_mdl_enabled, PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
26164 "Enable MDL for applications direct access InnoDB through InnoDB APIs",
26165 nullptr, nullptr, false);
26166
26167 static MYSQL_SYSVAR_BOOL(
26168 api_disable_rowlock, ib_disable_row_lock,
26169 PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
26170 "Disable row lock when direct access InnoDB through InnoDB APIs", nullptr,
26171 nullptr, false);
26172
26173 static MYSQL_SYSVAR_ULONG(api_trx_level, ib_trx_level_setting,
26174 PLUGIN_VAR_OPCMDARG,
26175 "InnoDB API transaction isolation level", nullptr,
26176 nullptr, 0, /* Default setting */
26177 0, /* Minimum value */
26178 3, 0); /* Maximum value */
26179
26180 static MYSQL_SYSVAR_ULONG(api_bk_commit_interval, ib_bk_commit_interval,
26181 PLUGIN_VAR_OPCMDARG,
26182 "Background commit interval in seconds", nullptr,
26183 nullptr, 5, /* Default setting */
26184 1, /* Minimum value */
26185 1024 * 1024 * 1024, 0); /* Maximum value */
26186
26187 static MYSQL_SYSVAR_ENUM(change_buffering, innodb_change_buffering,
26188 PLUGIN_VAR_RQCMDARG,
26189 "Buffer changes to reduce random access:"
26190 " OFF, ON, inserting, deleting, changing, or purging.",
26191 nullptr, nullptr, IBUF_USE_ALL,
26192 &innodb_change_buffering_typelib);
26193
26194 static MYSQL_SYSVAR_UINT(
26195 change_buffer_max_size, srv_change_buffer_max_size, PLUGIN_VAR_RQCMDARG,
26196 "Maximum on-disk size of change buffer in terms of percentage"
26197 " of the buffer pool.",
26198 nullptr, innodb_change_buffer_max_size_update, CHANGE_BUFFER_DEFAULT_SIZE,
26199 0, 50, 0);
26200
26201 static MYSQL_SYSVAR_ENUM(
26202 stats_method, srv_innodb_stats_method, PLUGIN_VAR_RQCMDARG,
26203 "Specifies how InnoDB index statistics collection code should"
26204 " treat NULLs. Possible values are NULLS_EQUAL (default),"
26205 " NULLS_UNEQUAL and NULLS_IGNORED",
26206 nullptr, nullptr, SRV_STATS_NULLS_EQUAL, &innodb_stats_method_typelib);
26207
26208 #if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
26209 static MYSQL_SYSVAR_UINT(
26210 change_buffering_debug, ibuf_debug, PLUGIN_VAR_RQCMDARG,
26211 "Debug flags for InnoDB change buffering (0=none, 2=crash at merge)",
26212 nullptr, nullptr, 0, 0, 2, 0);
26213
26214 static MYSQL_SYSVAR_BOOL(disable_background_merge,
26215 srv_ibuf_disable_background_merge,
26216 PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_RQCMDARG,
26217 "Disable change buffering merges by the master thread",
26218 nullptr, nullptr, false);
26219
26220 static MYSQL_SYSVAR_ENUM(
26221 compress_debug, srv_debug_compress, PLUGIN_VAR_RQCMDARG,
26222 "Compress all tables, without specifying the COMPRESS table attribute",
26223 nullptr, nullptr, Compression::NONE, &innodb_debug_compress_typelib);
26224 #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
26225
26226 #ifdef WITH_WSREP
26227 /* if rsync is being done on live/active node then it is important
26228 that innodb io write threads are not flushing/writing.
26229 FLUSH TABLE with READ LOCK will block external action but internal
26230 action or if the thread is actively writing then all such action
26231 needs to be avoided. rsync is like taking a snapshot at given
26232 point in time. If thread-1/2 are altering file-1/2 from innodb
26233 and both action are needed for complete data-directory to make sense
26234 then this sequence could break the rsync backed up copy.
26235 thread-1 write complete -> rsync -> thread-2 write complete */
26236
26237 /* An "update" method for innobase_disallow_writes variable. */
26238 3 static void innobase_disallow_writes_update(
26239 THD *thd, // in: thread handle <]
26240 SYS_VAR *var, // in: pointer to
26241 // system variable */
26242 void *var_ptr, // where the
26243 // formal string goes */
26244 const void *save) { // in: immediate result
26245 // from check function
26246 6 ib::warn() << "innodb_disallow_writes has been deprecated and will be"
26247 " removed in future release. Consider using read_only"
26248
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 " instead.";
26249
26250 3 *(bool *)var_ptr = *(bool *)save;
26251
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 ut_a(srv_allow_writes_event);
26252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (*(bool *)var_ptr)
26253 os_event_reset(srv_allow_writes_event);
26254 else
26255 3 os_event_set(srv_allow_writes_event);
26256 3 }
26257
26258 static MYSQL_SYSVAR_BOOL(disallow_writes, innobase_disallow_writes,
26259 PLUGIN_VAR_NOCMDOPT,
26260 "Tell InnoDB to stop any writes to disk (deprecated)",
26261 NULL, innobase_disallow_writes_update, false);
26262 #endif /* WITH_WSREP */
26263
26264 static MYSQL_SYSVAR_BOOL(
26265 random_read_ahead, srv_random_read_ahead, PLUGIN_VAR_NOCMDARG,
26266 "Whether to use read ahead for random access within an extent.", nullptr,
26267 nullptr, false);
26268
26269 static MYSQL_SYSVAR_ULONG(
26270 read_ahead_threshold, srv_read_ahead_threshold, PLUGIN_VAR_RQCMDARG,
26271 "Number of pages that must be accessed sequentially for InnoDB to"
26272 " trigger a readahead.",
26273 nullptr, nullptr, 56, 0, 64, 0);
26274
26275 static MYSQL_SYSVAR_STR(monitor_enable, innobase_enable_monitor_counter,
26276 PLUGIN_VAR_RQCMDARG, "Turn on a monitor counter",
26277 innodb_monitor_validate, innodb_enable_monitor_update,
26278 nullptr);
26279
26280 static MYSQL_SYSVAR_STR(monitor_disable, innobase_disable_monitor_counter,
26281 PLUGIN_VAR_RQCMDARG, "Turn off a monitor counter",
26282 innodb_monitor_validate, innodb_disable_monitor_update,
26283 nullptr);
26284
26285 static MYSQL_SYSVAR_STR(monitor_reset, innobase_reset_monitor_counter,
26286 PLUGIN_VAR_RQCMDARG, "Reset a monitor counter",
26287 innodb_monitor_validate, innodb_reset_monitor_update,
26288 nullptr);
26289
26290 static MYSQL_SYSVAR_STR(monitor_reset_all, innobase_reset_all_monitor_counter,
26291 PLUGIN_VAR_RQCMDARG,
26292 "Reset all values for a monitor counter",
26293 innodb_monitor_validate,
26294 innodb_reset_all_monitor_update, nullptr);
26295
26296 static MYSQL_SYSVAR_BOOL(status_output, srv_print_innodb_monitor,
26297 PLUGIN_VAR_OPCMDARG,
26298 "Enable InnoDB monitor output to the error log.",
26299 nullptr, nullptr, false);
26300
26301 static MYSQL_SYSVAR_BOOL(status_output_locks, srv_print_innodb_lock_monitor,
26302 PLUGIN_VAR_OPCMDARG,
26303 "Enable InnoDB lock monitor output to the error log."
26304 " Requires innodb_status_output=ON.",
26305 nullptr, nullptr, false);
26306
26307 static MYSQL_SYSVAR_BOOL(
26308 print_all_deadlocks, srv_print_all_deadlocks, PLUGIN_VAR_OPCMDARG,
26309 "Print all deadlocks to MySQL error log (off by default)", nullptr, nullptr,
26310 false);
26311
26312 static MYSQL_SYSVAR_BOOL(
26313 print_lock_wait_timeout_info, srv_print_lock_wait_timeout_info,
26314 PLUGIN_VAR_OPCMDARG,
26315 "Print lock wait timeout info to MySQL error log (off by default)", nullptr,
26316 nullptr, false);
26317
26318 static MYSQL_SYSVAR_ULONG(
26319 compression_failure_threshold_pct, zip_failure_threshold_pct,
26320 PLUGIN_VAR_OPCMDARG,
26321 "If the compression failure rate of a table is greater than this number"
26322 " more padding is added to the pages to reduce the failures. A value of"
26323 " zero implies no padding",
26324 nullptr, nullptr, 5, 0, 100, 0);
26325
26326 static MYSQL_SYSVAR_ULONG(
26327 compression_pad_pct_max, zip_pad_max, PLUGIN_VAR_OPCMDARG,
26328 "Percentage of empty space on a data page that can be reserved"
26329 " to make the page compressible.",
26330 nullptr, nullptr, 50, 0, 75, 0);
26331
26332 static MYSQL_SYSVAR_BOOL(read_only, srv_read_only_mode,
26333 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY |
26334 PLUGIN_VAR_NOPERSIST,
26335 "Start InnoDB in read only mode (off by default)",
26336 nullptr, nullptr, false);
26337
26338 static MYSQL_SYSVAR_BOOL(
26339 cmp_per_index_enabled, srv_cmp_per_index_enabled, PLUGIN_VAR_OPCMDARG,
26340 "Enable INFORMATION_SCHEMA.innodb_cmp_per_index,"
26341 " may have negative impact on performance (off by default)",
26342 nullptr, innodb_cmp_per_index_update, false);
26343
26344 static MYSQL_SYSVAR_ENUM(
26345 default_row_format, innodb_default_row_format, PLUGIN_VAR_RQCMDARG,
26346 "The default ROW FORMAT for all innodb tables created without explicit"
26347 " ROW_FORMAT. Possible values are REDUNDANT, COMPACT, and DYNAMIC."
26348 " The ROW_FORMAT value COMPRESSED is not allowed",
26349 nullptr, nullptr, DEFAULT_ROW_FORMAT_DYNAMIC,
26350 &innodb_default_row_format_typelib);
26351
26352 static MYSQL_SYSVAR_STR(
26353 redo_log_archive_dirs, meb::redo_log_archive_dirs,
26354 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
26355 "Limit the location of the redo log archive to the semicolon "
26356 "separated list of labeled directories",
26357 /*validate_func*/ meb::validate_redo_log_archive_dirs,
26358 /*update_func*/ nullptr, /*default*/ nullptr);
26359
26360 static MYSQL_SYSVAR_BOOL(redo_log_encrypt, srv_redo_log_encrypt,
26361 PLUGIN_VAR_OPCMDARG,
26362 "Enable or disable Encryption of REDO tablespace.",
26363 validate_innodb_redo_log_encrypt, nullptr, false);
26364
26365 static MYSQL_SYSVAR_BOOL(
26366 print_ddl_logs, srv_print_ddl_logs, PLUGIN_VAR_OPCMDARG,
26367 "Print all DDl logs to MySQL error log (off by default)", nullptr, nullptr,
26368 false);
26369
26370 #ifdef UNIV_DEBUG
26371 static MYSQL_SYSVAR_UINT(trx_rseg_n_slots_debug, trx_rseg_n_slots_debug,
26372 PLUGIN_VAR_RQCMDARG,
26373 "Debug flags for InnoDB to limit TRX_RSEG_N_SLOTS for "
26374 "trx_rsegf_undo_find_free()",
26375 nullptr, nullptr, 0, 0, 1024, 0);
26376
26377 static MYSQL_SYSVAR_UINT(
26378 limit_optimistic_insert_debug, btr_cur_limit_optimistic_insert_debug,
26379 PLUGIN_VAR_RQCMDARG,
26380 "Artificially limit the number of records per B-tree page (0=unlimited).",
26381 nullptr, nullptr, 0, 0, UINT_MAX32, 0);
26382
26383 static MYSQL_SYSVAR_BOOL(trx_purge_view_update_only_debug,
26384 srv_purge_view_update_only_debug, PLUGIN_VAR_NOCMDARG,
26385 "Pause actual purging any delete-marked records, but "
26386 "merely update the purge view."
26387 " It is to create artificially the situation the "
26388 "purge view have been updated"
26389 " but the each purges were not done yet.",
26390 nullptr, nullptr, false);
26391 // clang-format off
26392 static MYSQL_SYSVAR_ULONG(
26393 fil_make_page_dirty_debug,
26394 srv_fil_make_page_dirty_debug, PLUGIN_VAR_OPCMDARG,
26395 "Make the first page of the given tablespace dirty.",
26396 nullptr, innodb_make_page_dirty, UINT_MAX32, 0, UINT_MAX32, 0);
26397 // clang-format on
26398
26399 static MYSQL_SYSVAR_ULONG(saved_page_number_debug, srv_saved_page_number_debug,
26400 PLUGIN_VAR_OPCMDARG, "An InnoDB page number.",
26401 nullptr, innodb_save_page_no, 0, 0, UINT_MAX32, 0);
26402
26403 static MYSQL_SYSVAR_BOOL(page_cleaner_disabled_debug,
26404 innodb_page_cleaner_disabled_debug,
26405 PLUGIN_VAR_OPCMDARG, "Disable page cleaner", nullptr,
26406 buf_flush_page_cleaner_disabled_debug_update, false);
26407
26408 static MYSQL_SYSVAR_BOOL(dict_stats_disabled_debug,
26409 innodb_dict_stats_disabled_debug, PLUGIN_VAR_OPCMDARG,
26410 "Disable dict_stats thread", nullptr,
26411 dict_stats_disabled_debug_update, false);
26412
26413 static MYSQL_SYSVAR_BOOL(master_thread_disabled_debug,
26414 srv_master_thread_disabled_debug, PLUGIN_VAR_OPCMDARG,
26415 "Disable master thread", nullptr,
26416 srv_master_thread_disabled_debug_update, false);
26417
26418 static MYSQL_SYSVAR_BOOL(sync_debug, srv_sync_debug,
26419 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
26420 "Enable the sync debug checks", nullptr, nullptr,
26421 false);
26422
26423 static MYSQL_SYSVAR_BOOL(buffer_pool_debug, srv_buf_pool_debug,
26424 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
26425 "Enable buffer pool debug", nullptr, nullptr, false);
26426
26427 static MYSQL_SYSVAR_BOOL(ddl_log_crash_reset_debug,
26428 innodb_ddl_log_crash_reset_debug, PLUGIN_VAR_OPCMDARG,
26429 "Reset all crash injection counters to 1", nullptr,
26430 ddl_log_crash_reset, false);
26431
26432 #endif /* UNIV_DEBUG */
26433
26434 static MYSQL_SYSVAR_STR(directories, srv_innodb_directories,
26435 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY |
26436 PLUGIN_VAR_NOPERSIST,
26437 "List of directories 'dir1;dir2;..;dirN' to scan for "
26438 "tablespace files. Default is to scan "
26439 "'innodb-data-home-dir;innodb-undo-directory;datadir'",
26440 nullptr, nullptr, nullptr);
26441
26442 #ifdef UNIV_DEBUG
26443 /** Use this variable innodb_interpreter to execute debug code within InnoDB.
26444 The output is stored in the innodb_interpreter_output variable. */
26445 static MYSQL_THDVAR_STR(interpreter, PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOPERSIST,
26446 "Invoke InnoDB test interpreter with commands"
26447 " to be executed.",
26448 ib_interpreter_check, ib_interpreter_update, "init");
26449
26450 /** When testing commands are executed in the innodb_interpreter variable, the
26451 output is stored in this innodb_interpreter_output variable. */
26452 static MYSQL_THDVAR_STR(interpreter_output,
26453 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_MEMALLOC |
26454 PLUGIN_VAR_NOPERSIST,
26455 "Output from InnoDB testing module (ut0test).", nullptr,
26456 nullptr, "The Default Value");
26457
26458 54 char **thd_innodb_interpreter_output(THD *thd) {
26459 return (MYSQL_SYSVAR_NAME(interpreter_output)
26460 54 .resolve(thd, MYSQL_SYSVAR_NAME(interpreter_output).offset));
26461 }
26462
26463 54 char **thd_innodb_interpreter(THD *thd) {
26464 return MYSQL_SYSVAR_NAME(interpreter)
26465 54 .resolve(thd, MYSQL_SYSVAR_NAME(interpreter).offset);
26466 }
26467 #endif /* UNIV_DEBUG */
26468
26469 static const char *corrupt_table_action_names[] = {"assert", /* 0 */
26470 "warn", /* 1 */
26471 "salvage", /* 2 */
26472 NullS};
26473
26474 static TYPELIB corrupt_table_action_typelib = {
26475 array_elements(corrupt_table_action_names) - 1,
26476 "corrupt_table_action_typelib", corrupt_table_action_names, nullptr};
26477
26478 static MYSQL_SYSVAR_ENUM(
26479 corrupt_table_action, srv_pass_corrupt_table, PLUGIN_VAR_RQCMDARG,
26480 "Warn corruptions of user tables as 'corrupt table' instead of not "
26481 "crashing itself, "
26482 "when used with file_per_table. "
26483 "All file io for the datafile after detected as corrupt are disabled, "
26484 "except for the deletion.",
26485 nullptr, nullptr, 0, &corrupt_table_action_typelib);
26486
26487 static MYSQL_SYSVAR_STR(
26488 parallel_doublewrite_path, srv_parallel_doublewrite_path_deprecated,
26489 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOPERSIST,
26490 "Deprecated Percona-specific variable that was used to set path to the "
26491 "parallel doublewrite file and has no effect now. "
26492 "Use --innodb-doublewrite-dir instead.",
26493 nullptr, innodb_parallel_doublewrite_path_update, "xb_doublewrite");
26494
26495 static MYSQL_SYSVAR_BOOL(
26496 parallel_dblwr_encrypt, srv_parallel_dblwr_encrypt_deprecated,
26497 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOPERSIST,
26498 "Deprecated Percona-specific variable that was used to enable or "
26499 "disable encryption of parallel doublewrite buffer file and has no "
26500 "effect now.",
26501 nullptr, innodb_parallel_dblwr_encrypt_update, false);
26502
26503 static MYSQL_SYSVAR_UINT(
26504 compressed_columns_zip_level, srv_compressed_columns_zip_level,
26505 PLUGIN_VAR_RQCMDARG,
26506 "Compression level used for compressed columns. 0 is no compression"
26507 ", 1 is fastest and 9 is best compression. Default is 6.",
26508 nullptr, nullptr, DEFAULT_COMPRESSION_LEVEL, 0, 9, 0);
26509
26510 static MYSQL_SYSVAR_ULONG(
26511 compressed_columns_threshold, srv_compressed_columns_threshold,
26512 PLUGIN_VAR_RQCMDARG,
26513 "Compress column data if its length exceeds this value. Default is 96",
26514 nullptr, nullptr, 96, 1, ~0UL, 0);
26515
26516 static MYSQL_SYSVAR_BOOL(encrypt_online_alter_logs,
26517 srv_encrypt_online_alter_logs,
26518 PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
26519 "Encrypt online alter logs.", nullptr, nullptr, false);
26520
26521 static MYSQL_SYSVAR_UINT(
26522 encryption_threads, srv_n_fil_crypt_threads_requested, PLUGIN_VAR_RQCMDARG,
26523 "Number of threads performing background key rotation and "
26524 "scrubbing",
26525 innodb_encryption_threads_validate, innodb_encryption_threads_update, 0, 0,
26526 MAX_ENCRYPTION_THREADS, 0);
26527
26528 static MYSQL_SYSVAR_UINT(encryption_rotate_key_age,
26529 srv_fil_crypt_rotate_key_age, PLUGIN_VAR_RQCMDARG,
26530 "Key rotation - re-encrypt in background "
26531 "all pages that were encrypted with a key that "
26532 "many (or more) versions behind. Value 0 indicates "
26533 "that key rotation is disabled.",
26534 NULL, innodb_encryption_rotate_key_age_update, 1, 0,
26535 UINT_MAX32, 0);
26536
26537 static MYSQL_SYSVAR_UINT(encryption_rotation_iops, srv_n_fil_crypt_iops,
26538 PLUGIN_VAR_RQCMDARG,
26539 "Use this many iops for background key rotation", NULL,
26540 innodb_encryption_rotation_iops_update,
26541 srv_n_fil_crypt_iops, 0, UINT_MAX32, 0);
26542
26543 static SYS_VAR *innobase_system_variables[] = {
26544 MYSQL_SYSVAR(api_trx_level),
26545 MYSQL_SYSVAR(api_bk_commit_interval),
26546 MYSQL_SYSVAR(autoextend_increment),
26547 MYSQL_SYSVAR(dedicated_server),
26548 MYSQL_SYSVAR(buffer_pool_size),
26549 MYSQL_SYSVAR(buffer_pool_chunk_size),
26550 MYSQL_SYSVAR(buffer_pool_instances),
26551 MYSQL_SYSVAR(buffer_pool_filename),
26552 MYSQL_SYSVAR(buffer_pool_dump_now),
26553 MYSQL_SYSVAR(buffer_pool_dump_at_shutdown),
26554 MYSQL_SYSVAR(buffer_pool_in_core_file),
26555 MYSQL_SYSVAR(buffer_pool_dump_pct),
26556 #ifdef UNIV_DEBUG
26557 MYSQL_SYSVAR(buffer_pool_evict),
26558 #endif /* UNIV_DEBUG */
26559 MYSQL_SYSVAR(buffer_pool_load_now),
26560 MYSQL_SYSVAR(buffer_pool_load_abort),
26561 MYSQL_SYSVAR(buffer_pool_load_at_startup),
26562 MYSQL_SYSVAR(lru_scan_depth),
26563 MYSQL_SYSVAR(flush_neighbors),
26564 MYSQL_SYSVAR(checksum_algorithm),
26565 MYSQL_SYSVAR(log_checksums),
26566 MYSQL_SYSVAR(commit_concurrency),
26567 MYSQL_SYSVAR(concurrency_tickets),
26568 MYSQL_SYSVAR(compression_level),
26569 MYSQL_SYSVAR(ddl_buffer_size),
26570 MYSQL_SYSVAR(ddl_threads),
26571 MYSQL_SYSVAR(data_file_path),
26572 MYSQL_SYSVAR(temp_data_file_path),
26573 MYSQL_SYSVAR(temp_tablespace_encrypt),
26574 MYSQL_SYSVAR(sys_tablespace_encrypt),
26575 MYSQL_SYSVAR(data_home_dir),
26576 MYSQL_SYSVAR(extend_and_initialize),
26577 MYSQL_SYSVAR(doublewrite),
26578 MYSQL_SYSVAR(doublewrite_dir),
26579 MYSQL_SYSVAR(doublewrite_batch_size),
26580 MYSQL_SYSVAR(doublewrite_files),
26581 MYSQL_SYSVAR(doublewrite_pages),
26582 MYSQL_SYSVAR(stats_include_delete_marked),
26583 MYSQL_SYSVAR(api_enable_binlog),
26584 MYSQL_SYSVAR(api_enable_mdl),
26585 MYSQL_SYSVAR(api_disable_rowlock),
26586 MYSQL_SYSVAR(fast_shutdown),
26587 MYSQL_SYSVAR(read_io_threads),
26588 MYSQL_SYSVAR(write_io_threads),
26589 MYSQL_SYSVAR(file_per_table),
26590 MYSQL_SYSVAR(flush_log_at_timeout),
26591 MYSQL_SYSVAR(flush_log_at_trx_commit),
26592 MYSQL_SYSVAR(flush_method),
26593 MYSQL_SYSVAR(force_recovery),
26594 #ifdef UNIV_DEBUG
26595 MYSQL_SYSVAR(force_recovery_crash),
26596 #endif /* UNIV_DEBUG */
26597 MYSQL_SYSVAR(fill_factor),
26598 MYSQL_SYSVAR(ft_cache_size),
26599 MYSQL_SYSVAR(ft_total_cache_size),
26600 MYSQL_SYSVAR(ft_result_cache_limit),
26601 MYSQL_SYSVAR(ft_enable_stopword),
26602 MYSQL_SYSVAR(ft_max_token_size),
26603 MYSQL_SYSVAR(ft_min_token_size),
26604 MYSQL_SYSVAR(ft_num_word_optimize),
26605 MYSQL_SYSVAR(ft_sort_pll_degree),
26606 MYSQL_SYSVAR(force_load_corrupted),
26607 MYSQL_SYSVAR(lock_wait_timeout),
26608 MYSQL_SYSVAR(deadlock_detect),
26609 MYSQL_SYSVAR(page_size),
26610 MYSQL_SYSVAR(log_buffer_size),
26611 MYSQL_SYSVAR(log_file_size),
26612 MYSQL_SYSVAR(log_files_in_group),
26613 MYSQL_SYSVAR(redo_log_capacity),
26614 #ifdef UNIV_DEBUG_DEDICATED
26615 MYSQL_SYSVAR(debug_sys_mem_size),
26616 #endif /* UNIV_DEBUG_DEDICATED */
26617 MYSQL_SYSVAR(log_write_ahead_size),
26618 MYSQL_SYSVAR(log_group_home_dir),
26619 MYSQL_SYSVAR(log_writer_threads),
26620 MYSQL_SYSVAR(log_spin_cpu_abs_lwm),
26621 MYSQL_SYSVAR(log_spin_cpu_pct_hwm),
26622 MYSQL_SYSVAR(log_wait_for_flush_spin_hwm),
26623 #ifdef ENABLE_EXPERIMENT_SYSVARS
26624 MYSQL_SYSVAR(log_write_events),
26625 MYSQL_SYSVAR(log_flush_events),
26626 MYSQL_SYSVAR(log_recent_written_size),
26627 MYSQL_SYSVAR(log_recent_closed_size),
26628 MYSQL_SYSVAR(log_wait_for_write_spin_delay),
26629 MYSQL_SYSVAR(log_wait_for_write_timeout),
26630 MYSQL_SYSVAR(log_wait_for_flush_spin_delay),
26631 MYSQL_SYSVAR(log_wait_for_flush_timeout),
26632 MYSQL_SYSVAR(log_write_max_size),
26633 MYSQL_SYSVAR(log_writer_spin_delay),
26634 MYSQL_SYSVAR(log_writer_timeout),
26635 MYSQL_SYSVAR(log_checkpoint_every),
26636 MYSQL_SYSVAR(log_flusher_spin_delay),
26637 MYSQL_SYSVAR(log_flusher_timeout),
26638 MYSQL_SYSVAR(log_write_notifier_spin_delay),
26639 MYSQL_SYSVAR(log_write_notifier_timeout),
26640 MYSQL_SYSVAR(log_flush_notifier_spin_delay),
26641 MYSQL_SYSVAR(log_flush_notifier_timeout),
26642 #endif /* ENABLE_EXPERIMENT_SYSVARS */
26643 MYSQL_SYSVAR(log_compressed_pages),
26644 MYSQL_SYSVAR(max_dirty_pages_pct),
26645 MYSQL_SYSVAR(max_dirty_pages_pct_lwm),
26646 MYSQL_SYSVAR(adaptive_flushing_lwm),
26647 MYSQL_SYSVAR(adaptive_flushing),
26648 MYSQL_SYSVAR(flush_sync),
26649 MYSQL_SYSVAR(flushing_avg_loops),
26650 MYSQL_SYSVAR(max_purge_lag),
26651 MYSQL_SYSVAR(max_purge_lag_delay),
26652 MYSQL_SYSVAR(old_blocks_pct),
26653 MYSQL_SYSVAR(old_blocks_time),
26654 MYSQL_SYSVAR(open_files),
26655 MYSQL_SYSVAR(optimize_fulltext_only),
26656 MYSQL_SYSVAR(rollback_on_timeout),
26657 MYSQL_SYSVAR(ft_aux_table),
26658 MYSQL_SYSVAR(ft_enable_diag_print),
26659 MYSQL_SYSVAR(ft_server_stopword_table),
26660 MYSQL_SYSVAR(ft_user_stopword_table),
26661 MYSQL_SYSVAR(disable_sort_file_cache),
26662 MYSQL_SYSVAR(stats_on_metadata),
26663 MYSQL_SYSVAR(stats_transient_sample_pages),
26664 MYSQL_SYSVAR(stats_persistent),
26665 MYSQL_SYSVAR(stats_persistent_sample_pages),
26666 MYSQL_SYSVAR(stats_auto_recalc),
26667 MYSQL_SYSVAR(adaptive_hash_index),
26668 MYSQL_SYSVAR(adaptive_hash_index_parts),
26669 MYSQL_SYSVAR(stats_method),
26670 MYSQL_SYSVAR(replication_delay),
26671 MYSQL_SYSVAR(status_file),
26672 MYSQL_SYSVAR(strict_mode),
26673 MYSQL_SYSVAR(sort_buffer_size),
26674 MYSQL_SYSVAR(online_alter_log_max_size),
26675 MYSQL_SYSVAR(directories),
26676 MYSQL_SYSVAR(sync_spin_loops),
26677 MYSQL_SYSVAR(spin_wait_delay),
26678 MYSQL_SYSVAR(spin_wait_pause_multiplier),
26679 MYSQL_SYSVAR(fsync_threshold),
26680 MYSQL_SYSVAR(table_locks),
26681 MYSQL_SYSVAR(thread_concurrency),
26682 MYSQL_SYSVAR(adaptive_max_sleep_delay),
26683 MYSQL_SYSVAR(thread_sleep_delay),
26684 MYSQL_SYSVAR(tmpdir),
26685 MYSQL_SYSVAR(autoinc_lock_mode),
26686 MYSQL_SYSVAR(show_locks_held),
26687 MYSQL_SYSVAR(version),
26688 MYSQL_SYSVAR(use_native_aio),
26689 #ifdef HAVE_LIBNUMA
26690 MYSQL_SYSVAR(numa_interleave),
26691 #endif /* HAVE_LIBNUMA */
26692 MYSQL_SYSVAR(change_buffering),
26693 MYSQL_SYSVAR(change_buffer_max_size),
26694 #if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
26695 MYSQL_SYSVAR(change_buffering_debug),
26696 MYSQL_SYSVAR(disable_background_merge),
26697 #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
26698 #ifdef WITH_WSREP
26699 MYSQL_SYSVAR(disallow_writes),
26700 #endif /* WITH_WSREP */
26701 MYSQL_SYSVAR(random_read_ahead),
26702 MYSQL_SYSVAR(read_ahead_threshold),
26703 MYSQL_SYSVAR(read_only),
26704
26705 MYSQL_SYSVAR(io_capacity),
26706 MYSQL_SYSVAR(io_capacity_max),
26707 MYSQL_SYSVAR(idle_flush_pct),
26708 MYSQL_SYSVAR(page_cleaners),
26709 MYSQL_SYSVAR(monitor_enable),
26710 MYSQL_SYSVAR(monitor_disable),
26711 MYSQL_SYSVAR(monitor_reset),
26712 MYSQL_SYSVAR(monitor_reset_all),
26713 MYSQL_SYSVAR(purge_threads),
26714 MYSQL_SYSVAR(purge_batch_size),
26715 #ifdef UNIV_DEBUG
26716 MYSQL_SYSVAR(background_drop_list_empty),
26717 MYSQL_SYSVAR(purge_run_now),
26718 MYSQL_SYSVAR(purge_stop_now),
26719 MYSQL_SYSVAR(log_flush_now),
26720 MYSQL_SYSVAR(log_checkpoint_now),
26721 MYSQL_SYSVAR(log_checkpoint_fuzzy_now),
26722 MYSQL_SYSVAR(checkpoint_disabled),
26723 MYSQL_SYSVAR(buf_flush_list_now),
26724 MYSQL_SYSVAR(merge_threshold_set_all_debug),
26725 MYSQL_SYSVAR(semaphore_wait_timeout_debug),
26726 #endif /* UNIV_DEBUG */
26727 #if defined UNIV_DEBUG || defined UNIV_PERF_DEBUG
26728 MYSQL_SYSVAR(page_hash_locks),
26729 #ifdef UNIV_LINUX
26730 MYSQL_SYSVAR(sched_priority_purge),
26731 MYSQL_SYSVAR(sched_priority_io),
26732 MYSQL_SYSVAR(sched_priority_master),
26733 MYSQL_SYSVAR(priority_purge),
26734 MYSQL_SYSVAR(priority_master),
26735 #endif /* UNIV_LINUX */
26736 MYSQL_SYSVAR(cleaner_max_lru_time),
26737 MYSQL_SYSVAR(cleaner_max_flush_time),
26738 #endif /* defined UNIV_DEBUG || defined UNIV_PERF_DEBUG */
26739 MYSQL_SYSVAR(validate_tablespace_paths),
26740 MYSQL_SYSVAR(use_fdatasync),
26741 MYSQL_SYSVAR(status_output),
26742 MYSQL_SYSVAR(status_output_locks),
26743 MYSQL_SYSVAR(cleaner_lsn_age_factor),
26744 MYSQL_SYSVAR(empty_free_list_algorithm),
26745 MYSQL_SYSVAR(print_all_deadlocks),
26746 MYSQL_SYSVAR(print_lock_wait_timeout_info),
26747 MYSQL_SYSVAR(cmp_per_index_enabled),
26748 MYSQL_SYSVAR(max_undo_log_size),
26749 MYSQL_SYSVAR(purge_rseg_truncate_frequency),
26750 MYSQL_SYSVAR(undo_log_truncate),
26751 MYSQL_SYSVAR(undo_log_encrypt),
26752 MYSQL_SYSVAR(rollback_segments),
26753 MYSQL_SYSVAR(undo_directory),
26754 MYSQL_SYSVAR(temp_tablespaces_dir),
26755 MYSQL_SYSVAR(undo_tablespaces),
26756 MYSQL_SYSVAR(sync_array_size),
26757 MYSQL_SYSVAR(compression_failure_threshold_pct),
26758 MYSQL_SYSVAR(compression_pad_pct_max),
26759 MYSQL_SYSVAR(default_row_format),
26760 MYSQL_SYSVAR(redo_log_archive_dirs),
26761 MYSQL_SYSVAR(redo_log_encrypt),
26762 MYSQL_SYSVAR(print_ddl_logs),
26763 #ifdef UNIV_DEBUG
26764 MYSQL_SYSVAR(trx_rseg_n_slots_debug),
26765 MYSQL_SYSVAR(limit_optimistic_insert_debug),
26766 MYSQL_SYSVAR(trx_purge_view_update_only_debug),
26767 MYSQL_SYSVAR(fil_make_page_dirty_debug),
26768 MYSQL_SYSVAR(saved_page_number_debug),
26769 MYSQL_SYSVAR(compress_debug),
26770 MYSQL_SYSVAR(page_cleaner_disabled_debug),
26771 MYSQL_SYSVAR(dict_stats_disabled_debug),
26772 MYSQL_SYSVAR(master_thread_disabled_debug),
26773 MYSQL_SYSVAR(sync_debug),
26774 MYSQL_SYSVAR(buffer_pool_debug),
26775 MYSQL_SYSVAR(ddl_log_crash_reset_debug),
26776 MYSQL_SYSVAR(interpreter),
26777 MYSQL_SYSVAR(interpreter_output),
26778 #endif /* UNIV_DEBUG */
26779 MYSQL_SYSVAR(parallel_read_threads),
26780 MYSQL_SYSVAR(segment_reserve_factor),
26781 MYSQL_SYSVAR(corrupt_table_action),
26782 MYSQL_SYSVAR(parallel_doublewrite_path),
26783 MYSQL_SYSVAR(parallel_dblwr_encrypt),
26784 MYSQL_SYSVAR(compressed_columns_zip_level),
26785 MYSQL_SYSVAR(compressed_columns_threshold),
26786 MYSQL_SYSVAR(ft_ignore_stopwords),
26787 MYSQL_SYSVAR(encrypt_online_alter_logs),
26788 MYSQL_SYSVAR(encryption_threads),
26789 MYSQL_SYSVAR(encryption_rotate_key_age),
26790 MYSQL_SYSVAR(encryption_rotation_iops),
26791 MYSQL_SYSVAR(default_encryption_key_id),
26792 MYSQL_SYSVAR(records_in_range),
26793 MYSQL_SYSVAR(force_index_records_in_range),
26794 nullptr};
26795
26796 mysql_declare_plugin(innobase){
26797 MYSQL_STORAGE_ENGINE_PLUGIN,
26798 &innobase_storage_engine,
26799 innobase_hton_name,
26800 PLUGIN_AUTHOR_ORACLE,
26801 "Percona-XtraDB, Supports transactions, row-level locking, and foreign "
26802 "keys",
26803 PLUGIN_LICENSE_GPL,
26804 innodb_init, /* Plugin Init */
26805 nullptr, /* Plugin Check uninstall */
26806 innodb_deinit, /* Plugin Deinit */
26807 INNODB_VERSION_SHORT,
26808 innodb_status_variables_export, /* status variables */
26809 innobase_system_variables, /* system variables */
26810 nullptr, /* reserved */
26811 0, /* flags */
26812 },
26813 i_s_innodb_trx, i_s_innodb_cmp, i_s_innodb_cmp_reset, i_s_innodb_cmpmem,
26814 i_s_innodb_cmpmem_reset, i_s_innodb_cmp_per_index,
26815 i_s_innodb_cmp_per_index_reset, i_s_innodb_buffer_page,
26816 i_s_innodb_buffer_page_lru, i_s_innodb_buffer_stats,
26817 i_s_innodb_temp_table_info, i_s_innodb_metrics,
26818 i_s_innodb_ft_default_stopword, i_s_innodb_ft_deleted,
26819 i_s_innodb_ft_being_deleted, i_s_innodb_ft_config,
26820 i_s_innodb_ft_index_cache, i_s_innodb_ft_index_table, i_s_innodb_tables,
26821 i_s_innodb_tablestats, i_s_innodb_indexes, i_s_innodb_tablespaces,
26822 i_s_innodb_columns, i_s_innodb_virtual, i_s_innodb_cached_indexes,
26823 i_s_innodb_session_temp_tablespaces,
26824 i_s_innodb_tablespaces_encryption
26825
26826 mysql_declare_plugin_end;
26827
26828 /** @brief Initialize the default value of innodb_commit_concurrency.
26829
26830 Once InnoDB is running, the innodb_commit_concurrency must not change
26831 from zero to nonzero. (Bug #42101)
26832
26833 The initial default value is 0, and without this extra initialization,
26834 SET GLOBAL innodb_commit_concurrency=DEFAULT would set the parameter
26835 to 0, even if it was initially set to nonzero at the command line
26836 or configuration file. */
26837 9726 static void innobase_commit_concurrency_init_default() {
26838 9726 MYSQL_SYSVAR_NAME(commit_concurrency).def_val = innobase_commit_concurrency;
26839 9726 }
26840
26841 /****************************************************************************
26842 DS-MRR implementation
26843 ***************************************************************************/
26844
26845 /**
26846 Multi Range Read interface, DS-MRR calls */
26847 632328 int ha_innobase::multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param,
26848 uint n_ranges, uint mode,
26849 HANDLER_BUFFER *buf) {
26850 632328 m_ds_mrr.init(table);
26851
26852 632361 return (m_ds_mrr.dsmrr_init(seq, seq_init_param, n_ranges, mode, buf));
26853 }
26854
26855 3729039 int ha_innobase::multi_range_read_next(char **range_info) {
26856 3729039 return (m_ds_mrr.dsmrr_next(range_info));
26857 }
26858
26859 613359 ha_rows ha_innobase::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
26860 void *seq_init_param,
26861 uint n_ranges, uint *bufsz,
26862 uint *flags,
26863 Cost_estimate *cost) {
26864 /* See comments in ha_myisam::multi_range_read_info_const */
26865 613359 m_ds_mrr.init(table);
26866
26867 613396 return (m_ds_mrr.dsmrr_info_const(keyno, seq, seq_init_param, n_ranges, bufsz,
26868 613460 flags, cost));
26869 }
26870
26871 4106 ha_rows ha_innobase::multi_range_read_info(uint keyno, uint n_ranges, uint keys,
26872 uint *bufsz, uint *flags,
26873 Cost_estimate *cost) {
26874 4106 m_ds_mrr.init(table);
26875
26876 4106 return (m_ds_mrr.dsmrr_info(keyno, n_ranges, keys, bufsz, flags, cost));
26877 }
26878
26879 /**
26880 Index Condition Pushdown interface implementation */
26881
26882 /** InnoDB index push-down condition check
26883 @return ICP_NO_MATCH, ICP_MATCH, or ICP_OUT_OF_RANGE */
26884 ICP_RESULT
26885 1115590 innobase_index_cond(ha_innobase *h) /*!< in/out: pointer to ha_innobase */
26886 {
26887
1/2
✓ Branch 0 taken 1115590 times.
✗ Branch 1 not taken.
1115590 DBUG_TRACE;
26888
26889
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1115590 times.
1115590 assert(h->pushed_idx_cond);
26890
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1115590 times.
1115590 assert(h->pushed_idx_cond_keyno != MAX_KEY);
26891
26892
7/8
✓ Branch 0 taken 7880 times.
✓ Branch 1 taken 1107710 times.
✓ Branch 2 taken 7880 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 828 times.
✓ Branch 5 taken 7052 times.
✓ Branch 6 taken 828 times.
✓ Branch 7 taken 1114762 times.
1115590 if (h->end_range && h->compare_key_icp(h->end_range) > 0) {
26893 /* caller should return HA_ERR_END_OF_FILE already */
26894 828 return ICP_OUT_OF_RANGE;
26895 }
26896
26897
3/4
✓ Branch 0 taken 1114762 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1112998 times.
✓ Branch 3 taken 1764 times.
1114762 return h->pushed_idx_cond->val_int() ? ICP_MATCH : ICP_NO_MATCH;
26898 1115590 }
26899
26900 /** Get the computed value by supplying the base column values.
26901 @param[in,out] table the table whose virtual column template to be built */
26902 2 void innobase_init_vc_templ(dict_table_t *table) {
26903
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 dict_sys_mutex_enter();
26904
26905
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (table->vc_templ != nullptr) {
26906 dict_sys_mutex_exit();
26907
26908 return;
26909 }
26910
26911 2 table->vc_templ =
26912
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 ut::new_withkey<dict_vcol_templ_t>(UT_NEW_THIS_FILE_PSI_KEY);
26913 2 table->vc_templ->vtempl = nullptr;
26914
26915 2 std::string schema_name;
26916 2 std::string table_name;
26917
26918
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 table->get_table_name(schema_name, table_name);
26919
26920
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 THD *thd = current_thd;
26921
26922 {
26923
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 innodb_session_dict_mutex_guard_t guard(*thd_to_innodb_session(thd));
26924 #ifdef UNIV_DEBUG
26925 bool ret =
26926 #endif /* UNIV_DEBUG */
26927
26928
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 handler::my_prepare_gcolumn_template(
26929 thd, schema_name.c_str(), table_name.c_str(),
26930 &innobase_build_v_templ_callback, static_cast<void *>(table));
26931
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 ut_ad(!ret);
26932 2 }
26933
26934
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 dict_sys_mutex_exit();
26935 2 }
26936
26937 /** Change dbname and table name in table->vc_templ.
26938 @param[in,out] table the table whose virtual column template
26939 dbname and tbname to be renamed. */
26940 752 void innobase_rename_vc_templ(dict_table_t *table) {
26941 752 std::string schema_name;
26942 752 std::string table_name;
26943
26944 /* Get table and schema name in system character set. */
26945
1/2
✓ Branch 0 taken 752 times.
✗ Branch 1 not taken.
752 table->get_table_name(schema_name, table_name);
26946
26947
1/2
✓ Branch 0 taken 752 times.
✗ Branch 1 not taken.
752 table->vc_templ->db_name.assign(schema_name);
26948
1/2
✓ Branch 0 taken 752 times.
✗ Branch 1 not taken.
752 table->vc_templ->tb_name.assign(table_name);
26949 752 }
26950
26951 85 dfield_t *innobase_get_field_from_update_vector(dict_foreign_t *foreign,
26952 upd_t *update,
26953 uint32_t col_no) {
26954 85 dict_table_t *parent_table = foreign->referenced_table;
26955 85 dict_index_t *parent_index = foreign->referenced_index;
26956 uint32_t parent_field_no;
26957 uint32_t parent_col_no;
26958 uint32_t child_col_no;
26959
26960
2/2
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 23 times.
108 for (uint32_t i = 0; i < foreign->n_fields; i++) {
26961 85 child_col_no = foreign->foreign_index->get_col_no(i);
26962
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 62 times.
85 if (child_col_no != col_no) {
26963 23 continue;
26964 }
26965 62 parent_col_no = parent_index->get_col_no(i);
26966 62 parent_field_no = dict_table_get_nth_col_pos(parent_table, parent_col_no);
26967
1/2
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
62 for (uint32_t j = 0; j < update->n_fields; j++) {
26968 62 upd_field_t *parent_ufield = &update->fields[j];
26969
1/2
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
62 if (parent_ufield->field_no == parent_field_no) {
26970 62 return (&parent_ufield->new_val);
26971 }
26972 }
26973 }
26974
26975 23 return (nullptr);
26976 }
26977
26978 /** Get the computed value by supplying the base column values.
26979 @param[in,out] row the data row
26980 @param[in] col virtual column
26981 @param[in] index index on the virtual column
26982 @param[in,out] local_heap heap memory for processing large data etc.
26983 @param[in,out] heap memory heap that copies the actual index row
26984 @param[in] ifield index field
26985 @param[in] thd MySQL thread handle
26986 @param[in,out] mysql_table mysql table object
26987 @param[in] old_table during ALTER TABLE, this is the old table
26988 or NULL.
26989 @param[in] parent_update update vector for the parent row
26990 @param[in] foreign foreign key information
26991 @param[in] compress_heap
26992 @return the field filled with computed value, or NULL if just want
26993 to store the value in passed in "my_rec" */
26994 29708 dfield_t *innobase_get_computed_value(
26995 const dtuple_t *row, const dict_v_col_t *col, const dict_index_t *index,
26996 mem_heap_t **local_heap, mem_heap_t *heap, const dict_field_t *ifield,
26997 THD *thd, TABLE *mysql_table, const dict_table_t *old_table,
26998 upd_t *parent_update, dict_foreign_t *foreign, mem_heap_t **compress_heap) {
26999 byte rec_buf1[REC_VERSION_56_MAX_INDEX_COL_LEN];
27000 byte rec_buf2[REC_VERSION_56_MAX_INDEX_COL_LEN];
27001 byte *mysql_rec;
27002 byte *buf;
27003 dfield_t *field;
27004 ulint len;
27005 29708 ulong mv_length = 0;
27006 29708 const char *mv_data_ptr = nullptr;
27007
27008 const page_size_t page_size = (old_table == nullptr)
27009
1/2
✓ Branch 0 taken 3158 times.
✗ Branch 1 not taken.
3158 ? dict_table_page_size(index->table)
27010
3/4
✓ Branch 0 taken 3158 times.
✓ Branch 1 taken 26550 times.
✓ Branch 2 taken 26550 times.
✗ Branch 3 not taken.
29708 : dict_table_page_size(old_table);
27011
27012 29708 const dict_index_t *clust_index = nullptr;
27013
2/2
✓ Branch 0 taken 3158 times.
✓ Branch 1 taken 26550 times.
29708 if (old_table == nullptr) {
27014
1/2
✓ Branch 0 taken 3158 times.
✗ Branch 1 not taken.
3158 clust_index = index->table->first_index();
27015 } else {
27016
1/2
✓ Branch 0 taken 26550 times.
✗ Branch 1 not taken.
26550 clust_index = old_table->first_index();
27017 }
27018
27019 29708 ulint ret = 0;
27020
27021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29708 times.
29708 ut_ad(index->table->vc_templ);
27022
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29708 times.
29708 ut_ad(thd != nullptr);
27023
27024 29708 const mysql_row_templ_t *vctempl =
27025 29708 index->table->vc_templ
27026 29708 ->vtempl[index->table->vc_templ->n_col + col->v_pos];
27027
27028
2/2
✓ Branch 0 taken 28307 times.
✓ Branch 1 taken 1401 times.
29708 if (!heap ||
27029
2/2
✓ Branch 0 taken 1619 times.
✓ Branch 1 taken 26688 times.
28307 index->table->vc_templ->rec_len >= REC_VERSION_56_MAX_INDEX_COL_LEN) {
27030
2/2
✓ Branch 0 taken 978 times.
✓ Branch 1 taken 2042 times.
3020 if (*local_heap == nullptr) {
27031
1/2
✓ Branch 0 taken 978 times.
✗ Branch 1 not taken.
978 *local_heap = mem_heap_create(UNIV_PAGE_SIZE, UT_LOCATION_HERE);
27032 }
27033
27034 mysql_rec = static_cast<byte *>(
27035
1/2
✓ Branch 0 taken 3020 times.
✗ Branch 1 not taken.
3020 mem_heap_alloc(*local_heap, index->table->vc_templ->rec_len));
27036 3020 buf = static_cast<byte *>(
27037
1/2
✓ Branch 0 taken 3020 times.
✗ Branch 1 not taken.
3020 mem_heap_alloc(*local_heap, index->table->vc_templ->rec_len));
27038 } else {
27039 26688 mysql_rec = rec_buf1;
27040 26688 buf = rec_buf2;
27041 }
27042
27043
2/2
✓ Branch 0 taken 31136 times.
✓ Branch 1 taken 29708 times.
60844 for (ulint i = 0; i < col->num_base; i++) {
27044 31136 dict_col_t *base_col = col->base_col[i];
27045 31136 const dfield_t *row_field = nullptr;
27046 31136 uint32_t col_no = base_col->ind;
27047 31136 const mysql_row_templ_t *templ = index->table->vc_templ->vtempl[col_no];
27048 const byte *data;
27049
27050
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 31055 times.
31136 if (parent_update != nullptr) {
27051 row_field =
27052
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 innobase_get_field_from_update_vector(foreign, parent_update, col_no);
27053 }
27054
27055
2/2
✓ Branch 0 taken 31076 times.
✓ Branch 1 taken 60 times.
31136 if (row_field == nullptr) {
27056
1/2
✓ Branch 0 taken 31076 times.
✗ Branch 1 not taken.
31076 row_field = dtuple_get_nth_field(row, col_no);
27057 }
27058
27059 31136 data = static_cast<const byte *>(row_field->data);
27060 31136 len = row_field->len;
27061
27062
2/2
✓ Branch 0 taken 67 times.
✓ Branch 1 taken 31069 times.
31136 if (row_field->ext) {
27063
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 59 times.
67 if (*local_heap == nullptr) {
27064
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 *local_heap = mem_heap_create(UNIV_PAGE_SIZE, UT_LOCATION_HERE);
27065 }
27066
27067 67 data = lob::btr_copy_externally_stored_field(
27068
1/2
✓ Branch 0 taken 67 times.
✗ Branch 1 not taken.
67 thd_to_trx(thd), clust_index, &len, nullptr, data, page_size,
27069
2/4
✓ Branch 0 taken 67 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 67 times.
✗ Branch 3 not taken.
67 dfield_get_len(row_field), false, *local_heap);
27070 }
27071
27072
2/2
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 31067 times.
31136 if (len == UNIV_SQL_NULL) {
27073 69 mysql_rec[templ->mysql_null_byte_offset] |=
27074 69 (byte)templ->mysql_null_bit_mask;
27075 69 memcpy(mysql_rec + templ->mysql_col_offset,
27076 69 static_cast<const byte *>(index->table->vc_templ->default_rec +
27077 69 templ->mysql_col_offset),
27078 69 templ->mysql_col_len);
27079 } else {
27080 31067 row_sel_field_store_in_mysql_format(
27081 31067 mysql_rec + templ->mysql_col_offset, templ, index,
27082
1/2
✓ Branch 0 taken 31067 times.
✗ Branch 1 not taken.
31067 templ->clust_rec_field_no, (const byte *)data, len, compress_heap,
27083 ULINT_UNDEFINED);
27084
27085
2/2
✓ Branch 0 taken 14724 times.
✓ Branch 1 taken 16343 times.
31067 if (templ->mysql_null_bit_mask) {
27086 /* It is a nullable column with a
27087 non-NULL value */
27088 14724 mysql_rec[templ->mysql_null_byte_offset] &=
27089 14724 ~(byte)templ->mysql_null_bit_mask;
27090 }
27091 }
27092 }
27093
27094
1/2
✓ Branch 0 taken 29708 times.
✗ Branch 1 not taken.
29708 field = dtuple_get_nth_v_field(row, col->v_pos);
27095
27096 /* Bitmap for specifying which virtual columns the server
27097 should evaluate */
27098 29708 MY_BITMAP column_map;
27099 my_bitmap_map col_map_storage[bitmap_buffer_size(REC_MAX_N_FIELDS)];
27100
27101
1/2
✓ Branch 0 taken 29708 times.
✗ Branch 1 not taken.
29708 bitmap_init(&column_map, col_map_storage, REC_MAX_N_FIELDS);
27102
27103 /* Specify the column the server should evaluate */
27104 29708 bitmap_set_bit(&column_map, col->m_col.ind);
27105
27106 29708 Temp_table_handle tblhdl;
27107
27108
2/2
✓ Branch 0 taken 202 times.
✓ Branch 1 taken 29506 times.
29708 if (mysql_table == nullptr) {
27109
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 202 times.
202 if (vctempl->type == DATA_BLOB) {
27110 ulint max_len;
27111
27112 if (vctempl->mysql_col_len - 8 == 1) {
27113 /* This is for TINYBLOB only, which needs
27114 only 1 byte, other BLOBs won't be affected */
27115 max_len = 255;
27116 } else {
27117 max_len = DICT_MAX_FIELD_LEN_BY_FORMAT(index->table) + 1;
27118 }
27119
27120 byte *blob_mem = static_cast<byte *>(mem_heap_alloc(heap, max_len));
27121
27122 row_mysql_store_blob_ref(mysql_rec + vctempl->mysql_col_offset,
27123 vctempl->mysql_col_len, blob_mem, max_len, false,
27124 0, 0, compress_heap);
27125 }
27126
27127 /* open a temporary table handle */
27128
1/2
✓ Branch 0 taken 202 times.
✗ Branch 1 not taken.
202 mysql_table = tblhdl.open(thd, index->table->vc_templ->db_name.c_str(),
27129 202 index->table->vc_templ->tb_name.c_str());
27130 }
27131
1/2
✓ Branch 0 taken 29708 times.
✗ Branch 1 not taken.
29708 if (mysql_table) {
27132
5/6
✓ Branch 0 taken 25433 times.
✓ Branch 1 taken 4275 times.
✓ Branch 2 taken 25433 times.
✓ Branch 3 taken 4275 times.
✓ Branch 4 taken 29708 times.
✗ Branch 5 not taken.
59416 ret = handler::my_eval_gcolumn_expr(
27133 thd, mysql_table, &column_map, (uchar *)mysql_rec,
27134 29708 (col->m_col.is_multi_value() ? &mv_data_ptr : nullptr),
27135 29708 (col->m_col.is_multi_value() ? &mv_length : nullptr));
27136 } else {
27137 return nullptr;
27138 }
27139
27140
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 29674 times.
29708 if (ret != 0) {
27141 #ifdef INNODB_VIRTUAL_DEBUG
27142 ib::warn(ER_IB_MSG_581) << "Compute virtual column values failed ";
27143 fputs("InnoDB: Cannot compute value for following record ", stderr);
27144 dtuple_print(stderr, row);
27145 #endif /* INNODB_VIRTUAL_DEBUG */
27146 34 return (nullptr);
27147 }
27148
27149
2/2
✓ Branch 0 taken 29572 times.
✓ Branch 1 taken 102 times.
29674 if (vctempl->mysql_null_bit_mask &&
27150 29572 (mysql_rec[vctempl->mysql_null_byte_offset] &
27151
2/2
✓ Branch 0 taken 125 times.
✓ Branch 1 taken 29447 times.
29572 vctempl->mysql_null_bit_mask)) {
27152
1/2
✓ Branch 0 taken 125 times.
✗ Branch 1 not taken.
125 dfield_set_null(field);
27153 125 field->type.prtype |= DATA_VIRTUAL;
27154
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 59 times.
125 if (col->m_col.is_multi_value()) {
27155 66 field->type.prtype |= DATA_MULTI_VALUE;
27156 }
27157 125 return (field);
27158 }
27159
27160
2/2
✓ Branch 0 taken 25339 times.
✓ Branch 1 taken 4210 times.
29549 if (col->m_col.is_multi_value()) {
27161 Field_typed_array *fld;
27162 25339 fld = down_cast<Field_typed_array *>(mysql_table->field[col->m_col.ind]);
27163
1/2
✓ Branch 0 taken 25339 times.
✗ Branch 1 not taken.
25339 json_binary::Value v(json_binary::parse_binary(mv_data_ptr, mv_length));
27164 25339 multi_value_data *value = nullptr;
27165
27166 50678 bool succ = innobase_store_multi_value(
27167
2/4
✓ Branch 0 taken 25339 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25339 times.
✗ Branch 3 not taken.
25339 v, value, fld, field, dict_table_is_comp(index->table), heap);
27168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25339 times.
25339 if (!succ) {
27169 ut_error;
27170 }
27171
27172 25339 field->type.prtype |= DATA_MULTI_VALUE;
27173 } else {
27174 4210 row_mysql_store_col_in_innobase_format(
27175 4210 field, buf, true, mysql_rec + vctempl->mysql_col_offset,
27176
2/4
✓ Branch 0 taken 4210 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4210 times.
✗ Branch 3 not taken.
4210 vctempl->mysql_col_len, dict_table_is_comp(index->table), false,
27177 nullptr, 0, nullptr);
27178 }
27179 29549 field->type.prtype |= DATA_VIRTUAL;
27180
27181 29549 ulint max_prefix = col->m_col.max_prefix;
27182
27183
4/4
✓ Branch 0 taken 2506 times.
✓ Branch 1 taken 27043 times.
✓ Branch 2 taken 58 times.
✓ Branch 3 taken 2448 times.
29549 if (max_prefix && ifield &&
27184
2/4
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 58 times.
58 (ifield->prefix_len == 0 || ifield->prefix_len > col->m_col.max_prefix)) {
27185 max_prefix = ifield->prefix_len;
27186 }
27187
27188 /* If this is a prefix index, we only need a portion of the field */
27189
2/2
✓ Branch 0 taken 2506 times.
✓ Branch 1 taken 27043 times.
29549 if (max_prefix) {
27190 5012 len = dtype_get_at_most_n_mbchars(
27191 2506 col->m_col.prtype, col->m_col.mbminmaxlen, max_prefix, field->len,
27192
2/4
✓ Branch 0 taken 2506 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2506 times.
✗ Branch 3 not taken.
2506 static_cast<char *>(dfield_get_data(field)));
27193
1/2
✓ Branch 0 taken 2506 times.
✗ Branch 1 not taken.
2506 dfield_set_len(field, len);
27194 }
27195
27196
7/8
✓ Branch 0 taken 28205 times.
✓ Branch 1 taken 1344 times.
✓ Branch 2 taken 28205 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2866 times.
✓ Branch 5 taken 25339 times.
✓ Branch 6 taken 2866 times.
✓ Branch 7 taken 26683 times.
29549 if (heap != nullptr && !dfield_is_multi_value(field)) {
27197
1/2
✓ Branch 0 taken 2866 times.
✗ Branch 1 not taken.
2866 dfield_dup(field, heap);
27198 }
27199
27200 29549 return (field);
27201 29708 }
27202
27203 /** Attempt to push down an index condition.
27204 @param[in] keyno MySQL key number
27205 @param[in] idx_cond Index condition to be checked
27206 @return idx_cond if pushed; NULL if not pushed */
27207 2979 class Item *ha_innobase::idx_cond_push(uint keyno, class Item *idx_cond) {
27208
1/2
✓ Branch 0 taken 2979 times.
✗ Branch 1 not taken.
2979 DBUG_TRACE;
27209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2979 times.
2979 assert(keyno != MAX_KEY);
27210
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2979 times.
2979 assert(idx_cond != nullptr);
27211
27212 2979 pushed_idx_cond = idx_cond;
27213 2979 pushed_idx_cond_keyno = keyno;
27214 2979 in_range_check_pushed_down = true;
27215 /* We will evaluate the condition entirely */
27216 2979 return nullptr;
27217 2979 }
27218
27219 /** Find out if a Record_buffer is wanted by this handler, and what is the
27220 maximum buffer size the handler wants.
27221
27222 @param[out] max_rows gets set to the maximum number of records to allocate
27223 space for in the buffer
27224 @retval true if the handler wants a buffer
27225 @retval false if the handler does not want a buffer */
27226 663060 bool ha_innobase::is_record_buffer_wanted(ha_rows *const max_rows) const {
27227 /* If the scan won't be able to utilize the record buffer, return that
27228 we don't want one. The decision on whether to use a buffer is taken in
27229 row_search_mvcc(), look for the comment that starts with "Decide
27230 whether to prefetch extra rows." Let's do the same check here. */
27231
27232
2/2
✓ Branch 0 taken 411215 times.
✓ Branch 1 taken 251873 times.
663060 if (!m_prebuilt->can_prefetch_records()) {
27233 411215 *max_rows = 0;
27234 411215 return false;
27235 }
27236
27237 /* Limit the number of rows in the buffer to 100 for now. We may want
27238 to fine-tune this later, possibly taking record size and page size into
27239 account. The optimizer might allocate an even smaller buffer if it
27240 thinks a smaller number of rows will be fetched. */
27241 251873 *max_rows = 100;
27242 251873 return true;
27243 }
27244
27245 /** Return max limits for a single set of multi-valued keys
27246 @param[out] num_keys number of keys to store
27247 @param[out] keys_length total length of keys, bytes
27248 */
27249 28016 void ha_innobase::mv_key_capacity(uint *num_keys, size_t *keys_length) const {
27250 /* The limit of multi-value should be checked against undo page size,
27251 because a record length can not be longer than an undo page size.
27252 Actually, it should not be longer than half of a page size, but this
27253 can be checked for the full record.
27254
27255 The problem is, even if the number of multi-value fields are known,
27256 the actual number of multiple values per field are not known until
27257 the record itself gets inserted. So it's impossible to estimate the
27258 accurate max number of multiple values. Meanwhile, since other fields
27259 are not known in advance, so it's also impossible to estimate the
27260 accurate total key length.
27261
27262 Therefore, only the best effort can be done in this function.
27263 That is the estimation will be based on the INSERT to the table.
27264 And excluding all must have space, the left length is regarded
27265 as the keys_length. And the number of the keys would be got by
27266 keys_length / min(multi-value fields' length). Note if it is a
27267 variable length field, then it's data length is regarded as 1.
27268
27269 Furthermore, to make the calculation as simple as possible, some
27270 space cost would be ignored. This should not be a big deal, since
27271 the whole estimation is only a rough one.
27272
27273 So it's the greedy estimation which will try to give a most relaxed
27274 restriction on the table, to allow insert and update go as more as
27275 possible. The DB_UNDO_RECORD_TOO_BIG error would be raised if the
27276 actual user record exceeds the undo page size. */
27277
27278 28016 size_t free_space = trx_undo_max_free_space();
27279
27280 /* PK always takes place in log page, take that into account */
27281 28016 uint pk = table->s->primary_key;
27282
2/2
✓ Branch 0 taken 17591 times.
✓ Branch 1 taken 10425 times.
28016 if (pk != MAX_KEY) {
27283 17591 free_space -= table->s->key_info[pk].key_length;
27284 } else {
27285 /* Deduct default InnoDB's PK length */
27286 10425 free_space -= DATA_ROW_ID_LEN;
27287 }
27288
27289 /* Maybe the space for any normal virtual columns etc. should be
27290 considered here, however, no details can be know at this time point,
27291 so just ignore them all */
27292
27293 /* Find out the minimum key length so to get the maximum number
27294 of keys */
27295 28016 uint16_t min_mv_key_length = std::numeric_limits<uint16_t>::max();
27296
27297
2/2
✓ Branch 0 taken 89300 times.
✓ Branch 1 taken 26601 times.
115901 for (uint16_t i = 0; i < table->s->fields; ++i) {
27298 89300 Field *field = table->field[i];
27299
2/2
✓ Branch 0 taken 61008 times.
✓ Branch 1 taken 28292 times.
89300 if (!innobase_is_multi_value_fld(field)) {
27300 61008 continue;
27301 }
27302
27303 /* In case of variable length type, assume the minimum length of data,
27304 to make a maximum estimation of keys and allow users to insert as
27305 many keys as possible, under the constraint of total key length. */
27306
2/2
✓ Branch 0 taken 1415 times.
✓ Branch 1 taken 26877 times.
28292 if (field->type() == MYSQL_TYPE_VARCHAR) {
27307 1415 min_mv_key_length = 1;
27308 1415 break;
27309 }
27310
27311
2/2
✓ Branch 0 taken 26786 times.
✓ Branch 1 taken 91 times.
26877 if (min_mv_key_length > field->key_length()) {
27312 26786 min_mv_key_length = field->key_length();
27313 }
27314 }
27315
27316 28016 *keys_length = Multi_value_logger::get_keys_capacity(
27317 static_cast<uint32_t>(free_space), min_mv_key_length, num_keys);
27318 28016 }
27319
27320 /** Use this when the args are passed to the format string from
27321 messages_to_clients.txt directly as is.
27322
27323 Push a warning message to the client, it is a wrapper around:
27324
27325 void push_warning_printf(
27326 THD *thd, Sql_condition::enum_condition_level level,
27327 uint code, const char *format, ...);
27328 */
27329 2887 void ib_senderrf(THD *thd, /*!< in/out: session */
27330 ib_log_level_t level, /*!< in: warning level */
27331 uint32_t code, /*!< MySQL error code */
27332 ...) /*!< Args */
27333 {
27334 va_list args;
27335 2887 char *str = nullptr;
27336
1/2
✓ Branch 0 taken 2887 times.
✗ Branch 1 not taken.
2887 const char *format = innobase_get_err_msg(code);
27337
27338 /* If the caller wants to push a message to the client then
27339 the caller must pass a valid session handle. */
27340
27341
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2887 times.
2887 ut_a(thd != nullptr);
27342
27343 /* The error code must exist in the messages_to_clients.txt file. */
27344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2887 times.
2887 ut_a(format != nullptr);
27345
27346 2887 va_start(args, code);
27347
27348 #ifdef _WIN32
27349 int size = _vscprintf(format, args) + 1;
27350 if (size > 0) {
27351 str = static_cast<char *>(malloc(size));
27352 }
27353 if (str == NULL) {
27354 va_end(args);
27355 return; /* Watch for Out-Of-Memory */
27356 }
27357 str[size - 1] = 0x0;
27358 vsnprintf(str, size, format, args);
27359 #elif HAVE_VASPRINTF
27360 int ret;
27361 2887 ret = vasprintf(&str, format, args);
27362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2887 times.
2887 if (ret < 0) {
27363 va_end(args);
27364 return; /* Watch for Out-Of-Memory */
27365 }
27366 #else
27367 /* Use a fixed length string. */
27368 str = static_cast<char *>(malloc(BUFSIZ));
27369 if (str == NULL) {
27370 va_end(args);
27371 return; /* Watch for Out-Of-Memory */
27372 }
27373 vsnprintf(str, BUFSIZ, format, args);
27374 #endif /* _WIN32 */
27375
27376 Sql_condition::enum_severity_level l;
27377
27378 2887 l = Sql_condition::SL_NOTE;
27379
27380
2/5
✗ Branch 0 not taken.
✓ Branch 1 taken 2327 times.
✓ Branch 2 taken 560 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
2887 switch (level) {
27381 case IB_LOG_LEVEL_INFO:
27382 break;
27383 2327 case IB_LOG_LEVEL_WARN:
27384 2327 l = Sql_condition::SL_WARNING;
27385 2327 break;
27386 560 case IB_LOG_LEVEL_ERROR:
27387 /* We can't use push_warning_printf(), it is a hard error. */
27388
1/2
✓ Branch 0 taken 560 times.
✗ Branch 1 not taken.
560 my_printf_error(code, "%s", MYF(0), str);
27389 560 break;
27390 case IB_LOG_LEVEL_FATAL:
27391 l = Sql_condition::SEVERITY_END;
27392 break;
27393 #ifdef UNIV_HOTBACKUP
27394 default:
27395 break;
27396 #endif /* UNIV_HOTBACKUP */
27397 }
27398
27399
2/2
✓ Branch 0 taken 2327 times.
✓ Branch 1 taken 560 times.
2887 if (level != IB_LOG_LEVEL_ERROR) {
27400
1/2
✓ Branch 0 taken 2327 times.
✗ Branch 1 not taken.
2327 push_warning_printf(thd, l, code, "InnoDB: %s", str);
27401 }
27402
27403 2887 va_end(args);
27404 2887 free(str);
27405
27406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2887 times.
2887 if (level == IB_LOG_LEVEL_FATAL) {
27407 ut_error;
27408 }
27409 }
27410
27411 /** Use this when the args are first converted to a formatted string and then
27412 passed to the format string from messages_to_clients.txt. The error message
27413 format must be: "Some string ... %s".
27414
27415 Push a warning message to the client, it is a wrapper around:
27416
27417 void push_warning_printf(
27418 THD *thd, Sql_condition::enum_condition_level level,
27419 uint code, const char *format, ...);
27420 */
27421 305 void ib_errf(THD *thd, /*!< in/out: session */
27422 ib_log_level_t level, /*!< in: warning level */
27423 uint32_t code, /*!< MySQL error code */
27424 const char *format, /*!< printf format */
27425 ...) /*!< Args */
27426 {
27427 305 char *str = nullptr;
27428 va_list args;
27429
27430 /* If the caller wants to push a message to the client then
27431 the caller must pass a valid session handle. */
27432
27433
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 305 times.
305 ut_a(thd != nullptr);
27434
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 305 times.
305 ut_a(format != nullptr);
27435
27436 305 va_start(args, format);
27437
27438 #ifdef _WIN32
27439 int size = _vscprintf(format, args) + 1;
27440 if (size > 0) {
27441 str = static_cast<char *>(malloc(size));
27442 }
27443 if (str == NULL) {
27444 va_end(args);
27445 return; /* Watch for Out-Of-Memory */
27446 }
27447 str[size - 1] = 0x0;
27448 vsnprintf(str, size, format, args);
27449 #elif HAVE_VASPRINTF
27450 int ret;
27451 305 ret = vasprintf(&str, format, args);
27452
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 305 times.
305 if (ret < 0) {
27453 va_end(args);
27454 return; /* Watch for Out-Of-Memory */
27455 }
27456 #else
27457 /* Use a fixed length string. */
27458 str = static_cast<char *>(malloc(BUFSIZ));
27459 if (str == NULL) {
27460 va_end(args);
27461 return; /* Watch for Out-Of-Memory */
27462 }
27463 vsnprintf(str, BUFSIZ, format, args);
27464 #endif /* _WIN32 */
27465
27466
1/2
✓ Branch 0 taken 305 times.
✗ Branch 1 not taken.
305 ib_senderrf(thd, level, code, str);
27467
27468 305 va_end(args);
27469 305 free(str);
27470 }
27471 #endif /* !UNIV_HOTBACKUP */
27472
27473 /* Keep the first 16 characters as-is, since the url is sometimes used
27474 as an offset from this.*/
27475 const char *TROUBLESHOOTING_MSG = "Please refer to " REFMAN
27476 "innodb-troubleshooting.html"
27477 " for how to resolve the issue.";
27478
27479 const char *TROUBLESHOOT_DATADICT_MSG = "Please refer to " REFMAN
27480 "innodb-troubleshooting-datadict.html"
27481 " for how to resolve the issue.";
27482
27483 const char *BUG_REPORT_MSG =
27484 "Submit a detailed bug report to http://bugs.mysql.com";
27485
27486 const char *FORCE_RECOVERY_MSG = "Please refer to " REFMAN
27487 "forcing-innodb-recovery.html"
27488 " for information about forcing recovery.";
27489
27490 const char *ERROR_CREATING_MSG =
27491 "Please refer to " REFMAN "error-creating-innodb.html";
27492
27493 const char *OPERATING_SYSTEM_ERROR_MSG =
27494 "Refer to your operating system documentation for operating"
27495 " system error code information.";
27496
27497 const char *FOREIGN_KEY_CONSTRAINTS_MSG =
27498 "Please refer to " REFMAN
27499 "create-table-foreign-keys.html"
27500 " for correct foreign key definition.";
27501
27502 const char *INNODB_PARAMETERS_MSG =
27503 "Please refer to " REFMAN "innodb-parameters.html";
27504
27505 #ifndef UNIV_HOTBACKUP
27506 /**********************************************************************
27507 Converts an identifier from my_charset_filename to UTF-8 charset.
27508 @return result string length, as returned by strconvert() */
27509 527 uint innobase_convert_to_filename_charset(
27510 char *to, /* out: converted identifier */
27511 const char *from, /* in: identifier to convert */
27512 ulint len) /* in: length of 'to', in bytes */
27513 {
27514 uint errors;
27515 527 CHARSET_INFO *cs_to = &my_charset_filename;
27516 527 CHARSET_INFO *cs_from = system_charset_info;
27517
27518 return (static_cast<uint>(
27519
1/2
✓ Branch 0 taken 527 times.
✗ Branch 1 not taken.
527 strconvert(cs_from, from, cs_to, to, static_cast<size_t>(len), &errors)));
27520 }
27521
27522 /**********************************************************************
27523 Converts an identifier from my_charset_filename to UTF-8 charset.
27524 @return result string length, as returned by strconvert() */
27525 184 uint innobase_convert_to_system_charset(
27526 char *to, /* out: converted identifier */
27527 const char *from, /* in: identifier to convert */
27528 ulint len, /* in: length of 'to', in bytes */
27529 uint *errors) /* out: error return */
27530 {
27531 184 CHARSET_INFO *cs1 = &my_charset_filename;
27532 184 CHARSET_INFO *cs2 = system_charset_info;
27533
27534 return (static_cast<uint>(
27535 184 strconvert(cs1, from, cs2, to, static_cast<size_t>(len), errors)));
27536 }
27537
27538 /**********************************************************************
27539 Issue a warning that the row is too big. */
27540 5 void ib_warn_row_too_big(const dict_table_t *table) {
27541 /* If prefix is true then a 768-byte prefix is stored
27542 locally for BLOB fields. */
27543 5 const bool prefix = !dict_table_has_atomic_blobs(table);
27544
27545 const ulint free_space =
27546 5 page_get_free_space_of_empty(table->flags & DICT_TF_COMPACT) / 2;
27547
27548 5 THD *thd = current_thd;
27549
27550
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3 times.
5 push_warning_printf(
27551 thd, Sql_condition::SL_WARNING, HA_ERR_TOO_BIG_ROW,
27552 "Row size too large (> %lu). Changing some columns to TEXT"
27553 " or BLOB %smay help. In current row format, BLOB prefix of"
27554 " %d bytes is stored inline.",
27555 free_space,
27556 prefix ? "or using ROW_FORMAT=DYNAMIC or"
27557 " ROW_FORMAT=COMPRESSED "
27558 : "",
27559 prefix ? DICT_MAX_FIXED_COL_LEN : 0);
27560 5 }
27561
27562 /** Constructs fake dict_col_t describing column for foreign key type
27563 compatibility check from column description in Ha_fk_column_type form.
27564
27565 @note dict_col_t which is produced by this call is not valid for general
27566 purposes.
27567 @param[out] col dict_col_t filled by this function
27568 @param[in] fk_col_type foreign key type information */
27569 553374 static void innodb_fill_fake_column_struct(
27570 dict_col_t *col, const Ha_fk_column_type *fk_col_type) {
27571 ulint unsigned_type;
27572 ulint binary_type;
27573 ulint charset_no;
27574
27575 1106748 ulint mtype = get_innobase_type_from_mysql_dd_type(
27576 553374 &unsigned_type, &binary_type, &charset_no, fk_col_type->type,
27577
1/2
✓ Branch 0 taken 553374 times.
✗ Branch 1 not taken.
553374 fk_col_type->field_charset, fk_col_type->is_unsigned);
27578
27579 /* Fake prtype only contains info which is relevant for foreign key
27580 type compatibility check, especially the info used in cmp_cols_are_equal. */
27581 ulint fake_prtype =
27582
1/2
✓ Branch 0 taken 553374 times.
✗ Branch 1 not taken.
553374 dtype_form_prtype(unsigned_type | binary_type, charset_no);
27583
27584 1106748 ulint col_len = calc_pack_length(
27585 553374 fk_col_type->type, fk_col_type->char_length, fk_col_type->elements_count,
27586 /* InnoDB always treats BIT as char. */
27587
1/2
✓ Branch 0 taken 553374 times.
✗ Branch 1 not taken.
553374 true, fk_col_type->numeric_scale, fk_col_type->is_unsigned);
27588
27589
1/2
✓ Branch 0 taken 553374 times.
✗ Branch 1 not taken.
553374 dict_mem_fill_column_struct(col, 0 /* fake col_pos */, mtype, fake_prtype,
27590 col_len, true, UINT32_UNDEFINED, 0, 0);
27591 553374 }
27592
27593 /** Check if types of child and parent columns in foreign key are compatible.
27594
27595 @param[in] child_column_type Child column type description.
27596 @param[in] parent_column_type Parent column type description.
27597 @param[in] check_charsets Indicates whether we need to check
27598 that charsets of string columns
27599 match. Which is true in most cases.
27600
27601 @return True if types are compatible, False if not. */
27602 276687 static bool innodb_check_fk_column_compat(
27603 const Ha_fk_column_type *child_column_type,
27604 const Ha_fk_column_type *parent_column_type, bool check_charsets) {
27605 276687 dict_col_t dict_child_col, dict_parent_col;
27606
27607
1/2
✓ Branch 0 taken 276687 times.
✗ Branch 1 not taken.
276687 innodb_fill_fake_column_struct(&dict_child_col, child_column_type);
27608
1/2
✓ Branch 0 taken 276687 times.
✗ Branch 1 not taken.
276687 innodb_fill_fake_column_struct(&dict_parent_col, parent_column_type);
27609
27610 return (
27611
1/2
✓ Branch 0 taken 276687 times.
✗ Branch 1 not taken.
553374 cmp_cols_are_equal(&dict_child_col, &dict_parent_col, check_charsets));
27612 }
27613
27614 15589 static bool innobase_check_reserved_file_name(handlerton *, const char *name) {
27615 15589 CHARSET_INFO *ci = system_charset_info;
27616 15589 size_t logname_size = strlen(log_pre_8_0_30::FILE_BASE_NAME);
27617
27618 /* Name is smaller than reserved name */
27619
2/2
✓ Branch 0 taken 14343 times.
✓ Branch 1 taken 1246 times.
15589 if (strlen(name) < logname_size) {
27620 14343 return (false);
27621 }
27622 /* Do case insensitive comparison for name. */
27623
1/2
✓ Branch 0 taken 1271 times.
✗ Branch 1 not taken.
1271 for (uint i = 0; i < logname_size; i++) {
27624
3/6
✓ Branch 0 taken 1271 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1271 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1271 times.
1271 ut_ad(!my_isalpha(ci, log_pre_8_0_30::FILE_BASE_NAME[i]) ||
27625 my_islower(ci, log_pre_8_0_30::FILE_BASE_NAME[i]));
27626
27627
2/2
✓ Branch 0 taken 1246 times.
✓ Branch 1 taken 25 times.
1271 if (my_tolower(ci, name[i]) != log_pre_8_0_30::FILE_BASE_NAME[i]) {
27628 1246 return (false);
27629 }
27630 }
27631 return (true);
27632 }
27633 #endif /* !UNIV_HOTBACKUP */
27634